@opengeni/react 6.8.0 → 6.8.1-canary.41842879332001
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/app/app-state.js +8 -8
- package/dist/app/components/Composer.js +18 -18
- package/dist/app/components/agent/agent-capability-picker.js +6 -6
- package/dist/app/components/artifacts/artifact-library.js +6 -6
- package/dist/app/components/artifacts/artifact-viewer.js +18 -18
- package/dist/app/components/artifacts/chat-interactive-block.js +11 -11
- package/dist/app/components/artifacts/file-reach-dialog.js +6 -6
- package/dist/app/components/artifacts/inline-chat-image.js +19 -19
- package/dist/app/components/artifacts/retained-file-preview.js +20 -20
- package/dist/app/components/artifacts/retained-text-preview.js +3 -3
- package/dist/app/components/artifacts/site-audience.js +3 -3
- package/dist/app/components/artifacts/site-conversations.js +9 -9
- package/dist/app/components/artifacts/site-data.js +10 -10
- package/dist/app/components/artifacts/site-publishing-page.js +25 -25
- package/dist/app/components/artifacts/site-publishing.js +22 -22
- package/dist/app/components/artifacts/site-settings.js +24 -24
- package/dist/app/components/artifacts/site-version-menu.js +3 -3
- package/dist/app/components/billing-class-mark.js +3 -3
- package/dist/app/components/bots/bot-launch-strip.js +20 -20
- package/dist/app/components/bots/bot-template-dialog.js +26 -26
- package/dist/app/components/bots/bot-template-shortcuts.js +20 -20
- package/dist/app/components/bots/bot-templates-page.js +30 -30
- package/dist/app/components/capabilities/capability-detail-sheet.js +6 -6
- package/dist/app/components/capabilities/capability-logo-source.js +13 -13
- package/dist/app/components/capabilities/connector-tool-permissions.js +4 -4
- package/dist/app/components/capabilities/native-connect-setup.js +13 -13
- package/dist/app/components/capabilities/own-logins-shared-heads-up.js +3 -3
- package/dist/app/components/capabilities/prepared-mcp-setup-card.js +15 -15
- package/dist/app/components/capabilities/session-capability-card.js +47 -47
- package/dist/app/components/capabilities/session-chrome-card.js +20 -20
- package/dist/app/components/capabilities/session-custom-mcp-card.js +16 -16
- package/dist/app/components/capabilities/session-github-card.js +16 -16
- package/dist/app/components/capabilities/session-machine-card.js +19 -19
- package/dist/app/components/capabilities/session-personal-github-card.js +14 -14
- package/dist/app/components/capabilities/session-plugin-card.js +8 -8
- package/dist/app/components/command-menu/chat-status.js +15 -15
- package/dist/app/components/command-menu/chat-switcher.js +32 -32
- package/dist/app/components/command-menu/command-menu.js +36 -36
- package/dist/app/components/command-menu/shortcut-sheet.js +8 -8
- package/dist/app/components/composer-capabilities-menu-body.js +4 -4
- package/dist/app/components/composer-mobile-plus-panel.js +8 -8
- package/dist/app/components/composer-mobile-plus.js +1 -1
- package/dist/app/components/credit-required-gate.js +1 -1
- package/dist/app/components/credit-required-prompt.js +3 -3
- package/dist/app/components/desktop/app-shots.js +6 -6
- package/dist/app/components/desktop/computer-use.js +2 -2
- package/dist/app/components/desktop/this-computer.js +5 -5
- package/dist/app/components/feedback.js +3 -3
- package/dist/app/components/github-app-connect-launcher.js +1 -1
- package/dist/app/components/machines/connect-machine-dialog.js +11 -11
- package/dist/app/components/markdown.js +6 -6
- package/dist/app/components/models/models-ui.js +5 -5
- package/dist/app/components/my-things.js +4 -4
- package/dist/app/components/own-where-it-works.js +3 -3
- package/dist/app/components/personal-resource-attachment-surface.js +4 -4
- package/dist/app/components/pickers.js +5 -5
- package/dist/app/components/rail/channel-create-dialog.js +3 -3
- package/dist/app/components/rail/project-glyph.js +20 -20
- package/dist/app/components/rail/project-profile.js +27 -27
- package/dist/app/components/rail/rail-context.js +1 -1
- package/dist/app/components/rail/rail-sections.js +55 -55
- package/dist/app/components/rail/session-header.js +47 -47
- package/dist/app/components/rail/session-list.js +53 -53
- package/dist/app/components/rail/session-row-content.js +4 -4
- package/dist/app/components/rail/session-row-hover-details.js +14 -14
- package/dist/app/components/rail/session-shell.js +73 -73
- package/dist/app/components/rail/site-session-group-heading.js +8 -8
- package/dist/app/components/session/agent-configuration-panel.js +12 -12
- package/dist/app/components/session/banners.js +8 -8
- package/dist/app/components/session/console-new-conversation.js +39 -39
- package/dist/app/components/session/descendant-requests.js +36 -36
- package/dist/app/components/session/editable-artifacts-workspace.js +16 -16
- package/dist/app/components/session/failed-session-banner.js +6 -6
- package/dist/app/components/session/failure-recovery-boundary.js +3 -3
- package/dist/app/components/session/human-input-delegation-record.js +2 -2
- package/dist/app/components/session/human-input.js +33 -33
- package/dist/app/components/session/inspector.js +43 -43
- package/dist/app/components/session/message-actions.js +3 -3
- package/dist/app/components/session/message-resource-attachments.js +10 -10
- package/dist/app/components/session/model-recovery-notice.js +3 -3
- package/dist/app/components/session/new-session-settings-menu.js +6 -6
- package/dist/app/components/session/new-session-setup-strip.js +21 -21
- package/dist/app/components/session/sandbox-recovery-actions.js +3 -3
- package/dist/app/components/session/sandbox-switcher.js +7 -7
- package/dist/app/components/session/sandbox-workspace.js +48 -48
- package/dist/app/components/session/search-markdown-highlight.js +7 -7
- package/dist/app/components/session/search-results-view.js +8 -8
- package/dist/app/components/session/session-admin-access.js +4 -4
- package/dist/app/components/session/session-admission-notice.js +4 -4
- package/dist/app/components/session/session-avatar-picker.js +21 -21
- package/dist/app/components/session/session-avatar.js +19 -19
- package/dist/app/components/session/session-machine-access-notice.js +4 -4
- package/dist/app/components/session/session-profile-dialog.js +25 -25
- package/dist/app/components/session/session-profile-editor.js +26 -26
- package/dist/app/components/session/session-retention.js +3 -3
- package/dist/app/components/session/session-search-dialog.js +8 -8
- package/dist/app/components/session/session-tenancy-control.js +2 -2
- package/dist/app/components/session/session-usage-limit-section.js +4 -4
- package/dist/app/components/session/share-chat-dialog.js +5 -5
- package/dist/app/components/session/subagents.js +8 -8
- package/dist/app/components/session/subscription-account-indicator.js +6 -6
- package/dist/app/components/settings/row-select.js +4 -4
- package/dist/app/components/transcription-settings.js +6 -6
- package/dist/app/components/ui/destructive-confirm.js +5 -5
- package/dist/app/components/usage/usage-entry.js +3 -3
- package/dist/app/components/window-bar.js +9 -9
- package/dist/app/components/workspace-composer-plus.js +16 -16
- package/dist/app/components/workspace-reach.js +4 -4
- package/dist/app/embed/session-app.js +156 -156
- package/dist/app/lib/actions/actions-provider.js +8 -8
- package/dist/app/lib/agent-capabilities.js +3 -3
- package/dist/app/lib/codex-usage-query.js +2 -2
- package/dist/app/lib/composer-connectors.js +14 -14
- package/dist/app/lib/console-site.js +2 -2
- package/dist/app/lib/console-text.js +2 -2
- package/dist/app/lib/events.js +12 -12
- package/dist/app/lib/failed-session-copy.js +3 -3
- package/dist/app/lib/model-access-onboarding.js +3 -3
- package/dist/app/lib/move-chat-to-machine.js +3 -3
- package/dist/app/lib/session-branch-cache.js +8 -8
- package/dist/app/lib/session-create.js +4 -4
- package/dist/app/lib/session-group-pagination.js +8 -8
- package/dist/app/lib/session-hover-facts.js +13 -13
- package/dist/app/lib/session-model.js +2 -2
- package/dist/app/lib/session-pins.js +1 -1
- package/dist/app/lib/session-rail.js +5 -5
- package/dist/app/lib/session-rename.js +3 -3
- package/dist/app/lib/sessions-group.d.ts +5 -3
- package/dist/app/lib/sessions-group.js +7 -7
- package/dist/app/lib/site-tool-consent-dialog.js +7 -7
- package/dist/app/lib/site-tool-consent.js +1 -1
- package/dist/app/lib/turn-failure-analytics.js +4 -4
- package/dist/app/lib/use-follow-up-repositories.js +3 -3
- package/dist/app/lib/use-workspace-machines.js +4 -4
- package/dist/app/lib/use-workspace-model-catalog.js +3 -3
- package/dist/app/lib/use-workspace-rigs.js +2 -2
- package/dist/app/lib/workspace-navigation-preference.js +4 -4
- package/dist/app/lib/workspace-scope-context.js +3 -3
- package/dist/app/routes/artifacts.js +48 -48
- package/dist/app/routes/retained-artifact.js +32 -32
- package/dist/app/routes/session.js +94 -94
- package/dist/app/routes/sessions-index-hydration.js +5 -5
- package/dist/app/routes/sessions-index.js +76 -76
- package/dist/app/routes/site-view.js +55 -55
- package/dist/artifacts-document.js +4 -4
- package/dist/artifacts-presentation.js +4 -4
- package/dist/artifacts-spreadsheet.js +4 -4
- package/dist/artifacts.js +10 -10
- package/dist/automations.js +10 -10
- package/dist/{browser-viewer-ZHQDVHZ2.js → browser-viewer-H7PKY67P.js} +4 -4
- package/dist/{chat-interactive-block-VSDD6X3M.js → chat-interactive-block-47TCT4DN.js} +5 -5
- package/dist/{chunk-7Z76QP64.js → chunk-2QH3Q6Z2.js} +35 -5
- package/dist/chunk-2QH3Q6Z2.js.map +1 -0
- package/dist/{chunk-5MHMCE2G.js → chunk-2X2B6D5G.js} +3 -3
- package/dist/{chunk-OCXEY7HE.js → chunk-3BUI5DT7.js} +2 -2
- package/dist/{chunk-OSJ366KR.js → chunk-3FWP3TD3.js} +29 -29
- package/dist/{chunk-PWUSSSSL.js → chunk-3G5IA36N.js} +2 -2
- package/dist/{chunk-RGR57NYY.js → chunk-3NK4JAHL.js} +2 -2
- package/dist/{chunk-XUOYNJPB.js → chunk-3O7UZRWM.js} +24 -24
- package/dist/{chunk-JV3UI7BH.js → chunk-3OR6HMA4.js} +3 -3
- package/dist/{chunk-MV2CLIO6.js → chunk-3PC45I5N.js} +6 -6
- package/dist/{chunk-SJYTQLN3.js → chunk-3PI2BYK5.js} +3 -3
- package/dist/{chunk-DCEQCGVN.js → chunk-3PNA2P2Z.js} +2 -2
- package/dist/{chunk-ESXAECZ3.js → chunk-3XBZKF3K.js} +2 -2
- package/dist/{chunk-SBXSKRFA.js → chunk-45OGYO3S.js} +3 -3
- package/dist/{chunk-M3FDGRB4.js → chunk-4A7TKVNX.js} +3 -3
- package/dist/{chunk-RHXYO4H2.js → chunk-4BXRGXTD.js} +2 -2
- package/dist/{chunk-CV4VVLPZ.js → chunk-4HQAJA3T.js} +2 -2
- package/dist/{chunk-VCJQQYRE.js → chunk-4X2A3KPB.js} +4 -4
- package/dist/{chunk-OCXTTKVA.js → chunk-555K37A7.js} +2 -2
- package/dist/{chunk-EBIVTDEG.js → chunk-57L5ZXDS.js} +2 -2
- package/dist/{chunk-3L465FBR.js → chunk-5IADORIV.js} +6 -6
- package/dist/{chunk-SK5S2PCK.js → chunk-5IZQT4TE.js} +14 -14
- package/dist/chunk-5IZQT4TE.js.map +1 -0
- package/dist/{chunk-ZW5YTIH3.js → chunk-5PB46DAA.js} +1 -1
- package/dist/{chunk-ZW5YTIH3.js.map → chunk-5PB46DAA.js.map} +1 -1
- package/dist/{chunk-PVB4YVDP.js → chunk-5Y2O2432.js} +2 -2
- package/dist/{chunk-OOOSGPJL.js → chunk-6572EFE4.js} +1 -1
- package/dist/{chunk-YMI27QPF.js → chunk-6BG5HCUP.js} +2 -2
- package/dist/{chunk-QRECBCJM.js → chunk-6EXFJWII.js} +2 -2
- package/dist/{chunk-74CBR5YE.js → chunk-6PNRUGOK.js} +2 -2
- package/dist/{chunk-PUUEI4W3.js → chunk-6RJEY6TC.js} +5 -5
- package/dist/{chunk-DLVIRJGK.js → chunk-727GL2YY.js} +2 -2
- package/dist/{chunk-J2BTILRR.js → chunk-7FGYLFW6.js} +2 -2
- package/dist/{chunk-MKDFYE2E.js → chunk-7IMWTFEG.js} +2 -2
- package/dist/{chunk-FER6EVIY.js → chunk-7POKH54R.js} +2 -2
- package/dist/{chunk-H6BX6WOW.js → chunk-7T26IH6W.js} +3 -3
- package/dist/{chunk-R33SBMB7.js → chunk-7XQRVZZQ.js} +3 -3
- package/dist/{chunk-NFCS5WYC.js → chunk-A3SPPXMC.js} +3 -3
- package/dist/{chunk-DQPIEQGP.js → chunk-A7CWPDEH.js} +2 -2
- package/dist/{chunk-3PM3M2Q6.js → chunk-AGOYVKTI.js} +2 -2
- package/dist/{chunk-OBGOLHCP.js → chunk-AIQKZUPB.js} +3 -3
- package/dist/{chunk-GSCGKJNK.js → chunk-AMYDHG3S.js} +2 -2
- package/dist/{chunk-U4LTPFD2.js → chunk-APJPB6TX.js} +2 -2
- package/dist/{chunk-SP44O3OU.js → chunk-APLGT5EI.js} +2 -2
- package/dist/{chunk-M3HGBO2Y.js → chunk-ATNKMGLO.js} +1 -1
- package/dist/{chunk-4O2XWOLZ.js → chunk-AVX4CZQ3.js} +3 -3
- package/dist/{chunk-CXAN2FHF.js → chunk-B46MK44K.js} +6 -6
- package/dist/{chunk-RMCLFSMX.js → chunk-BBKUPEGG.js} +2 -2
- package/dist/{chunk-J2WY42FA.js → chunk-BES6OQE3.js} +2 -2
- package/dist/{chunk-GU7T2S5N.js → chunk-BM2N26SH.js} +2 -2
- package/dist/{chunk-HEGV4QMS.js → chunk-C3NS74PZ.js} +2 -2
- package/dist/{chunk-752WXSDN.js → chunk-C56ABB5V.js} +2 -2
- package/dist/{chunk-77SYIH6O.js → chunk-C6MATJQ5.js} +2 -2
- package/dist/{chunk-KUE5BOQE.js → chunk-CRX47CO6.js} +4 -4
- package/dist/{chunk-QPQ7R77C.js → chunk-CUIV2XPO.js} +3 -1
- package/dist/chunk-CUIV2XPO.js.map +1 -0
- package/dist/{chunk-GTHCHCWW.js → chunk-D33KWZQJ.js} +3 -3
- package/dist/{chunk-AH3DGOTK.js → chunk-D7E3BSCX.js} +2 -2
- package/dist/{chunk-OJWDNNW3.js → chunk-DFR3TMTZ.js} +5 -5
- package/dist/{chunk-WYGTAQMX.js → chunk-DICC75CU.js} +2 -2
- package/dist/{chunk-736RUNIA.js → chunk-DJ2LMKKX.js} +4 -4
- package/dist/{chunk-4F3AEJI6.js → chunk-DJI4D7PM.js} +4 -4
- package/dist/{chunk-LVELUUK6.js → chunk-DSZUQL4W.js} +2 -2
- package/dist/{chunk-MT2R57SF.js → chunk-DVF246BE.js} +2 -2
- package/dist/{chunk-OI6VI6SU.js → chunk-DVOWBHWN.js} +8 -8
- package/dist/{chunk-PZKHST7A.js → chunk-E2KPRSA4.js} +2 -2
- package/dist/{chunk-EKJHOWTZ.js → chunk-E3LMLWEB.js} +4 -4
- package/dist/{chunk-QURYQFDN.js → chunk-EDC7X7PW.js} +2 -2
- package/dist/{chunk-HYEIA25Y.js → chunk-EDSMULHU.js} +2 -2
- package/dist/{chunk-U6552Q3T.js → chunk-EQQOZ6DD.js} +2 -2
- package/dist/{chunk-IFSXVU2S.js → chunk-ERBDQ2GY.js} +2 -2
- package/dist/{chunk-IZXYFWA4.js → chunk-EWI73URG.js} +13 -13
- package/dist/{chunk-N3FM4BNA.js → chunk-EZ6LFN33.js} +2 -2
- package/dist/{chunk-4K64EKM7.js → chunk-F7YL6DPR.js} +4 -4
- package/dist/{chunk-ICAMYP5M.js → chunk-FIGFXMUP.js} +2 -2
- package/dist/{chunk-54U6ZBEX.js → chunk-FJRJK67G.js} +3 -3
- package/dist/{chunk-E5KOWRDU.js → chunk-FLHB2NZT.js} +2 -2
- package/dist/{chunk-OWET7EY2.js → chunk-FRSZSL2S.js} +19 -13
- package/dist/{chunk-OWET7EY2.js.map → chunk-FRSZSL2S.js.map} +1 -1
- package/dist/{chunk-D3PTVN2I.js → chunk-FUGGM76A.js} +2 -2
- package/dist/{chunk-QQIZMVAJ.js → chunk-FWLLGNGP.js} +51 -49
- package/dist/chunk-FWLLGNGP.js.map +1 -0
- package/dist/{chunk-TDTD66BK.js → chunk-FXPZAZYT.js} +2 -2
- package/dist/{chunk-KO3OHHY2.js → chunk-GAGAM4MT.js} +2 -2
- package/dist/{chunk-TK5FWVZR.js → chunk-GESGH3HY.js} +3 -3
- package/dist/{chunk-2VJOSU4H.js → chunk-GI4PWKXI.js} +2 -2
- package/dist/{chunk-KFNZZ2N6.js → chunk-GJTEBAZ7.js} +2 -2
- package/dist/{chunk-LTJFV2JI.js → chunk-GNCGEW7F.js} +2 -2
- package/dist/{chunk-34NV52R3.js → chunk-GOMUNPB6.js} +4 -4
- package/dist/{chunk-7YTR3UFO.js → chunk-GPWE5UD7.js} +8 -5
- package/dist/chunk-GPWE5UD7.js.map +1 -0
- package/dist/{chunk-LIJNVIT3.js → chunk-GUMUILEI.js} +3 -3
- package/dist/{chunk-7NLF35YL.js → chunk-GVGNHBFT.js} +4 -4
- package/dist/{chunk-K3D7IQQP.js → chunk-GW4YI3FB.js} +6 -6
- package/dist/{chunk-D5TIVCXG.js → chunk-GXKCV7X7.js} +2 -2
- package/dist/{chunk-2J77TWGH.js → chunk-H467EQA6.js} +3 -3
- package/dist/{chunk-3OK7Y6ES.js → chunk-HE77VDDR.js} +2 -2
- package/dist/{chunk-UO35OEOX.js → chunk-HT65RGCX.js} +3 -3
- package/dist/{chunk-G6ICCGJ3.js → chunk-HVQSFTE7.js} +2 -2
- package/dist/{chunk-G5UQBTXY.js → chunk-HXJPDC76.js} +2 -2
- package/dist/{chunk-GIWFLWXG.js → chunk-I6LQW24C.js} +4 -4
- package/dist/{chunk-467WDSOK.js → chunk-I7A6S5YL.js} +2 -2
- package/dist/{chunk-AAS7OWV6.js → chunk-IADS4ZYD.js} +3 -3
- package/dist/{chunk-Y3XZEKDQ.js → chunk-IJWMWCGR.js} +2 -2
- package/dist/{chunk-SGH7I7OY.js → chunk-IWFO6KOU.js} +2 -2
- package/dist/{chunk-GMHIOYB7.js → chunk-IYC6QGV2.js} +4 -4
- package/dist/{chunk-2OXSB2OL.js → chunk-J2TZIFRC.js} +3 -2
- package/dist/chunk-J2TZIFRC.js.map +1 -0
- package/dist/{chunk-3NNAC43A.js → chunk-J5AODKJO.js} +2 -2
- package/dist/{chunk-DIP7YALH.js → chunk-JKI3LMLH.js} +2 -2
- package/dist/{chunk-IJR6VOLU.js → chunk-JSYRWOCE.js} +2 -2
- package/dist/{chunk-CEMSIU4Z.js → chunk-JTQTWO4D.js} +5 -5
- package/dist/{chunk-JHZRAYI4.js → chunk-JWSRFXRN.js} +2 -2
- package/dist/chunk-JWSRFXRN.js.map +1 -0
- package/dist/{chunk-BASI553K.js → chunk-KBTKAAHM.js} +4 -4
- package/dist/{chunk-OYOFPNLC.js → chunk-KD7VEMWY.js} +4 -4
- package/dist/{chunk-3DRLCX5V.js → chunk-KPGFGRSA.js} +2 -2
- package/dist/{chunk-PLYVGZIN.js → chunk-KWFDEJFI.js} +1 -1
- package/dist/{chunk-FNXCFIPW.js → chunk-KYLEH4OF.js} +2 -2
- package/dist/{chunk-WXF2RTS4.js → chunk-L7FJTFJN.js} +2 -2
- package/dist/{chunk-KI46GKMD.js → chunk-L7VVQOSY.js} +7 -7
- package/dist/{chunk-M5IQVMLR.js → chunk-LAZ2QZTJ.js} +11 -4
- package/dist/chunk-LAZ2QZTJ.js.map +1 -0
- package/dist/chunk-LKLQVANM.js +2 -0
- package/dist/{chunk-YNTLWCF4.js → chunk-LLYEAZ4E.js} +3 -3
- package/dist/{chunk-4Z5X7PLC.js → chunk-LWM7JUW6.js} +3 -3
- package/dist/{chunk-CHU3RDV4.js → chunk-LXKV4ND3.js} +3 -3
- package/dist/{chunk-AB5IW227.js → chunk-LYLICEQO.js} +3 -3
- package/dist/{chunk-PSM3CU7N.js → chunk-M3OZOCIK.js} +46 -39
- package/dist/chunk-M3OZOCIK.js.map +1 -0
- package/dist/{chunk-OTW25A6I.js → chunk-M5GRI5K4.js} +3 -3
- package/dist/{chunk-X2QJXDE4.js → chunk-MF65PKKF.js} +8 -8
- package/dist/{chunk-EDDKPIIV.js → chunk-MJ4XIOPM.js} +2 -2
- package/dist/{chunk-FLWQJDJ5.js → chunk-MMPJJQG3.js} +6 -6
- package/dist/{chunk-T67LTMSW.js → chunk-MOU54FGD.js} +10 -10
- package/dist/{chunk-LQKVNREV.js → chunk-NAWHQ4IL.js} +3 -3
- package/dist/{chunk-ZBHGNE2J.js → chunk-NBHBB2VV.js} +3 -3
- package/dist/{chunk-PF2WU2IL.js → chunk-ND4IQJUM.js} +120 -17
- package/dist/chunk-ND4IQJUM.js.map +1 -0
- package/dist/{chunk-U5UGM5XD.js → chunk-NMOZDAEZ.js} +5 -5
- package/dist/{chunk-D74Z2N4K.js → chunk-NZA4R3BE.js} +2 -2
- package/dist/{chunk-WRMUXZ7C.js → chunk-OB2CX7PJ.js} +3 -3
- package/dist/{chunk-YJSCLGAW.js → chunk-OB4I4OIT.js} +3 -3
- package/dist/{chunk-DWJ6J3YW.js → chunk-OKQW2FPL.js} +4 -4
- package/dist/{chunk-2GCHGWNE.js → chunk-ORLX6A3C.js} +3 -3
- package/dist/{chunk-EBTUPRRQ.js → chunk-P5N4EYFW.js} +4 -4
- package/dist/{chunk-JKL5S7UQ.js → chunk-PL4JE3NI.js} +6 -6
- package/dist/{chunk-OP2GD6QW.js → chunk-PNUHKDY2.js} +2 -2
- package/dist/{chunk-MZY3VKKM.js → chunk-PWJE7D6V.js} +2 -2
- package/dist/{chunk-RISUROBM.js → chunk-PYE27I6J.js} +4 -4
- package/dist/{chunk-SPD4ULVB.js → chunk-PYMROAWS.js} +2 -1
- package/dist/chunk-PYMROAWS.js.map +1 -0
- package/dist/{chunk-Q5K2J5GG.js → chunk-Q74FQK3A.js} +13 -3
- package/dist/chunk-Q74FQK3A.js.map +1 -0
- package/dist/{chunk-R5QAL43H.js → chunk-QIJHK6P4.js} +2 -2
- package/dist/{chunk-AJBDAVX3.js → chunk-QK3A23NP.js} +7 -7
- package/dist/{chunk-CYDXCILL.js → chunk-QLWDNAOV.js} +7 -7
- package/dist/{chunk-BQYRZIZ7.js → chunk-QS6DQBVJ.js} +2 -2
- package/dist/{chunk-3PZ3LRPV.js → chunk-QSUVFPG3.js} +3 -3
- package/dist/{chunk-PYB4BFEC.js → chunk-QUC5MLTN.js} +3 -3
- package/dist/{chunk-WDASYY4S.js → chunk-QVT5AWPI.js} +6 -6
- package/dist/{chunk-K4DQS2ML.js → chunk-QZC6WCBR.js} +4 -4
- package/dist/{chunk-HWVPLFIW.js → chunk-RAHNICPP.js} +2 -2
- package/dist/{chunk-H6MJFMHZ.js → chunk-RME6RGIW.js} +3 -3
- package/dist/{chunk-XMBOLFFS.js → chunk-RQIB2F53.js} +2 -2
- package/dist/{chunk-OXQ2SXVC.js → chunk-RUA72NQY.js} +2 -2
- package/dist/{chunk-UMX6DZME.js → chunk-SCJHWN4X.js} +2 -2
- package/dist/{chunk-HTMQGS63.js → chunk-SIXBDT5F.js} +8 -8
- package/dist/{chunk-ZAX4XQLN.js → chunk-SPK3T4JK.js} +2 -2
- package/dist/{chunk-WTSQUCHB.js → chunk-SSN2YSST.js} +3 -3
- package/dist/{chunk-5MIBQ4P5.js → chunk-SYJCDX5V.js} +2 -2
- package/dist/{chunk-NQ2CPQJF.js → chunk-SYL7LCRA.js} +26 -3
- package/dist/chunk-SYL7LCRA.js.map +1 -0
- package/dist/{chunk-ZR5EKJT6.js → chunk-T6276OXI.js} +2 -2
- package/dist/{chunk-DEHLWZSI.js → chunk-T7OARG4N.js} +4 -4
- package/dist/{chunk-77BHKC43.js → chunk-TF5L3BEV.js} +1 -1
- package/dist/{chunk-GOCODNQS.js → chunk-TF6Z7BOP.js} +2 -2
- package/dist/{chunk-WIFDNUKD.js → chunk-TJDXWZMO.js} +3 -3
- package/dist/{chunk-SFIXTOOJ.js → chunk-TL5ATBHZ.js} +3 -3
- package/dist/{chunk-XZCCEKPW.js → chunk-TMOHIOMT.js} +6 -6
- package/dist/{chunk-AVXDIRRW.js → chunk-UI5X63YC.js} +2 -2
- package/dist/{chunk-6QK65ZWM.js → chunk-UIY7BDZC.js} +3 -3
- package/dist/{chunk-VATYK3JQ.js → chunk-UMBFMEO7.js} +3 -3
- package/dist/{chunk-UU5FBVRX.js → chunk-UU5G7OA4.js} +2 -2
- package/dist/{chunk-EGKARC53.js → chunk-UZUCYCF4.js} +2 -2
- package/dist/{chunk-LPKJ77EK.js → chunk-V2A7G7S7.js} +2 -2
- package/dist/{chunk-CH4UQ4NO.js → chunk-V5G4TKRC.js} +5 -5
- package/dist/{chunk-UBRQ3PQD.js → chunk-VKAVW34W.js} +2 -2
- package/dist/{chunk-JV5ULONH.js → chunk-VVLEVNTQ.js} +36 -36
- package/dist/{chunk-44JWVYJB.js → chunk-VW7X7TWZ.js} +2 -2
- package/dist/{chunk-3CDJSKDW.js → chunk-VWA2CHSL.js} +3 -3
- package/dist/{chunk-IN3VQFKS.js → chunk-W43HZPM7.js} +2 -2
- package/dist/{chunk-SXGJL7UT.js → chunk-WHGD7Q2L.js} +14 -14
- package/dist/{chunk-XOIDUM2H.js → chunk-WNXKYEVN.js} +1 -1
- package/dist/{chunk-TKQL7EDB.js → chunk-WSA7UBX4.js} +2 -2
- package/dist/{chunk-AJDGP2N4.js → chunk-WZ5TQJ3T.js} +19 -19
- package/dist/{chunk-FBA2NXYH.js → chunk-X3TGNSOG.js} +3 -3
- package/dist/{chunk-R4JA5JFI.js → chunk-X4WXYI3N.js} +3 -3
- package/dist/{chunk-Q5EZNBPI.js → chunk-XIQ3AIAJ.js} +3 -3
- package/dist/{chunk-S27VZ5DO.js → chunk-XWYT4LEL.js} +6 -6
- package/dist/{chunk-477DTTMH.js → chunk-Y3PU75OC.js} +3 -3
- package/dist/{chunk-4JXPLTWV.js → chunk-Y5ZWX5YS.js} +2 -2
- package/dist/{chunk-4BWMAGJJ.js → chunk-YA5PABND.js} +3 -3
- package/dist/{chunk-VXORMNU4.js → chunk-YBHAAULA.js} +67 -2
- package/dist/chunk-YBHAAULA.js.map +1 -0
- package/dist/{chunk-OGU73VUN.js → chunk-YBPRR2QS.js} +2 -2
- package/dist/{chunk-TNSJFZ6Q.js → chunk-YDYR7XQE.js} +4 -4
- package/dist/{chunk-GTRAH4FG.js → chunk-YG6V2LQH.js} +2 -2
- package/dist/{chunk-XVLEBB4Y.js → chunk-YUXA7ALE.js} +2 -2
- package/dist/{chunk-SN2WENRP.js → chunk-YWHQDXPB.js} +3 -3
- package/dist/{chunk-BFFNINCC.js → chunk-YWRR5R7B.js} +3 -3
- package/dist/{chunk-FSDQQQIA.js → chunk-YYRK7A4N.js} +3 -3
- package/dist/{chunk-MRECRNVU.js → chunk-Z26CDLUV.js} +5 -5
- package/dist/{chunk-OYCK4JRS.js → chunk-Z27EXLMQ.js} +2 -2
- package/dist/{chunk-UTRNLNCW.js → chunk-Z7GDH7W2.js} +3 -3
- package/dist/{chunk-PRT4J2DL.js → chunk-ZGVLSAWL.js} +2 -2
- package/dist/{chunk-OK7BQMCI.js → chunk-ZM6Q5NQN.js} +9 -9
- package/dist/components/message-timeline.d.ts +10 -2
- package/dist/composer.js +8 -8
- package/dist/{computer-viewer-5LKRCEVQ.js → computer-viewer-SROXREYD.js} +5 -5
- package/dist/connect.js +12 -12
- package/dist/desktop-dictation.js +8 -8
- package/dist/desktop.js +2 -2
- package/dist/editor.js +2 -2
- package/dist/{embedded-new-voice-GHJRY3YL.js → embedded-new-voice-EIQY2VBF.js} +5 -5
- package/dist/{embedded-voice-ASQXBSTX.js → embedded-voice-LMWNH7F7.js} +5 -5
- package/dist/{fleet-decision-row-U7LDVBEM.js → fleet-decision-row-X2G56ZRA.js} +2 -2
- package/dist/hooks/use-recordings.d.ts +4 -2
- package/dist/in-chat-connect-model.js +5 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +66 -60
- package/dist/interaction.js +5 -5
- package/dist/{latest-question-RNVF262Q.js → latest-question-KA7AQYVI.js} +2 -2
- package/dist/machines.js +3 -3
- package/dist/meetings/recorder-context.d.ts +6 -1
- package/dist/meetings/recorder-panel.d.ts +2 -5
- package/dist/meetings-recorder.js +1 -1
- package/dist/meetings.js +22 -21
- package/dist/meetings.js.map +1 -1
- package/dist/messages/en.d.ts +2 -0
- package/dist/messages.js +1 -1
- package/dist/{model-policy-picker-menu-E6XKMFTA.js → model-policy-picker-menu-SHWPT5VA.js} +4 -4
- package/dist/{payment-page-card-DJDKV2LW.js → payment-page-card-NNVUISN4.js} +4 -4
- package/dist/{platform-activity-row-MSDCSMET.js → platform-activity-row-7UDWSAHK.js} +2 -2
- package/dist/{queue-surface-implementation-GUAIG6TK.js → queue-surface-implementation-BUXSO24N.js} +5 -5
- package/dist/realtime.js +4 -4
- package/dist/{recorder-host-2MYDJPQW.js → recorder-host-POX54CFT.js} +5 -5
- package/dist/recordings.js +4 -4
- package/dist/{sandbox-files-W5W2LW4K.js → sandbox-files-33QD7DW2.js} +6 -6
- package/dist/session-app.js +156 -156
- package/dist/{session-connect-cards-HPH7JOZP.js → session-connect-cards-CXGNVA2A.js} +9 -9
- package/dist/session-list-model.js +2 -2
- package/dist/{session-realtime-SDTKFFIR.js → session-realtime-CVDSEULB.js} +3 -3
- package/dist/session-realtime.js +2 -2
- package/dist/session-ui.js +33 -33
- package/dist/session.d.ts +3 -2
- package/dist/session.js +16 -10
- package/dist/sites.js +2 -2
- package/dist/terminal.js +2 -2
- package/dist/this-computer.js +3 -3
- package/dist/timeline/index.d.ts +3 -2
- package/dist/timeline/projection.d.ts +52 -0
- package/dist/timeline/turn-summary-model.d.ts +4 -3
- package/dist/timeline/types.d.ts +8 -2
- package/dist/timeline/use-timeline-pauses.d.ts +12 -0
- package/dist/timeline/work-presentation.d.ts +4 -3
- package/dist/{timeline-annotation-markers-FNILLWNU.js → timeline-annotation-markers-5J5TM5IP.js} +2 -2
- package/dist/{timeline-annotation-selection-MBCIDO2Q.js → timeline-annotation-selection-WLY7FB7F.js} +2 -2
- package/dist/{timeline-annotations-dialog-JPNKLOTE.js → timeline-annotations-dialog-67VRFKJU.js} +3 -3
- package/dist/timeline-model.js +2 -2
- package/dist/ui/access-list.js +5 -5
- package/dist/ui/cadence-picker.js +4 -4
- package/dist/ui/choice-cards.js +3 -3
- package/dist/ui/confirm-dialog.js +2 -2
- package/dist/ui/copy-field.js +3 -3
- package/dist/ui/detail-page.js +2 -2
- package/dist/ui/detail-sheet.js +2 -2
- package/dist/ui/disclosure.js +3 -3
- package/dist/ui/email-chips-input.js +3 -3
- package/dist/ui/field.js +2 -2
- package/dist/ui/flush-form-page.js +3 -3
- package/dist/ui/form-dialog.js +2 -2
- package/dist/ui/list-row.js +3 -3
- package/dist/ui/relative-time.js +2 -2
- package/dist/ui/revision-history.js +4 -4
- package/dist/ui/role-select.js +5 -5
- package/dist/ui/select-menu.js +3 -3
- package/dist/ui/usage-meter.js +3 -3
- package/dist/usage.js +2 -2
- package/dist/workbench.js +4 -4
- package/package.json +6 -5
- package/src/app/components/rail/session-row-content.tsx +27 -0
- package/src/app/lib/session-branch-cache.tsx +1 -0
- package/src/app/lib/session-pins.tsx +1 -0
- package/src/app/lib/session-row-paused.test.tsx +183 -0
- package/src/app/lib/sessions-group-channels.test.ts +4 -4
- package/src/app/lib/sessions-group.tsx +62 -4
- package/src/app/routes/session.tsx +2 -0
- package/src/components/message-timeline.tsx +14 -2
- package/src/components/session-conversation.tsx +2 -1
- package/src/components/timeline-annotations.tsx +4 -1
- package/src/components/timeline-settlement.ts +1 -1
- package/src/hooks/use-recordings.ts +5 -0
- package/src/index.ts +5 -0
- package/src/meetings/recorder-context.tsx +28 -5
- package/src/meetings/recorder-panel.tsx +13 -5
- package/src/meetings/recorder-workspace.test.tsx +57 -8
- package/src/messages/en.ts +2 -0
- package/src/session.ts +8 -1
- package/src/timeline/index.ts +4 -1
- package/src/timeline/projection.ts +228 -16
- package/src/timeline/turn-summary-model.ts +4 -3
- package/src/timeline/turn-summary.tsx +15 -2
- package/src/timeline/types.ts +8 -2
- package/src/timeline/use-timeline-pauses.ts +105 -0
- package/src/timeline/work-presentation.ts +13 -4
- package/dist/chunk-2OXSB2OL.js.map +0 -1
- package/dist/chunk-7YTR3UFO.js.map +0 -1
- package/dist/chunk-7Z76QP64.js.map +0 -1
- package/dist/chunk-JHZRAYI4.js.map +0 -1
- package/dist/chunk-M5IQVMLR.js.map +0 -1
- package/dist/chunk-NQ2CPQJF.js.map +0 -1
- package/dist/chunk-O2UPPN5M.js +0 -2
- package/dist/chunk-PF2WU2IL.js.map +0 -1
- package/dist/chunk-PSM3CU7N.js.map +0 -1
- package/dist/chunk-Q5K2J5GG.js.map +0 -1
- package/dist/chunk-QPQ7R77C.js.map +0 -1
- package/dist/chunk-QQIZMVAJ.js.map +0 -1
- package/dist/chunk-SK5S2PCK.js.map +0 -1
- package/dist/chunk-SPD4ULVB.js.map +0 -1
- package/dist/chunk-VXORMNU4.js.map +0 -1
- /package/dist/{browser-viewer-ZHQDVHZ2.js.map → browser-viewer-H7PKY67P.js.map} +0 -0
- /package/dist/{chat-interactive-block-VSDD6X3M.js.map → chat-interactive-block-47TCT4DN.js.map} +0 -0
- /package/dist/{chunk-5MHMCE2G.js.map → chunk-2X2B6D5G.js.map} +0 -0
- /package/dist/{chunk-OCXEY7HE.js.map → chunk-3BUI5DT7.js.map} +0 -0
- /package/dist/{chunk-OSJ366KR.js.map → chunk-3FWP3TD3.js.map} +0 -0
- /package/dist/{chunk-PWUSSSSL.js.map → chunk-3G5IA36N.js.map} +0 -0
- /package/dist/{chunk-RGR57NYY.js.map → chunk-3NK4JAHL.js.map} +0 -0
- /package/dist/{chunk-XUOYNJPB.js.map → chunk-3O7UZRWM.js.map} +0 -0
- /package/dist/{chunk-JV3UI7BH.js.map → chunk-3OR6HMA4.js.map} +0 -0
- /package/dist/{chunk-MV2CLIO6.js.map → chunk-3PC45I5N.js.map} +0 -0
- /package/dist/{chunk-SJYTQLN3.js.map → chunk-3PI2BYK5.js.map} +0 -0
- /package/dist/{chunk-DCEQCGVN.js.map → chunk-3PNA2P2Z.js.map} +0 -0
- /package/dist/{chunk-ESXAECZ3.js.map → chunk-3XBZKF3K.js.map} +0 -0
- /package/dist/{chunk-SBXSKRFA.js.map → chunk-45OGYO3S.js.map} +0 -0
- /package/dist/{chunk-M3FDGRB4.js.map → chunk-4A7TKVNX.js.map} +0 -0
- /package/dist/{chunk-RHXYO4H2.js.map → chunk-4BXRGXTD.js.map} +0 -0
- /package/dist/{chunk-CV4VVLPZ.js.map → chunk-4HQAJA3T.js.map} +0 -0
- /package/dist/{chunk-VCJQQYRE.js.map → chunk-4X2A3KPB.js.map} +0 -0
- /package/dist/{chunk-OCXTTKVA.js.map → chunk-555K37A7.js.map} +0 -0
- /package/dist/{chunk-EBIVTDEG.js.map → chunk-57L5ZXDS.js.map} +0 -0
- /package/dist/{chunk-3L465FBR.js.map → chunk-5IADORIV.js.map} +0 -0
- /package/dist/{chunk-PVB4YVDP.js.map → chunk-5Y2O2432.js.map} +0 -0
- /package/dist/{chunk-OOOSGPJL.js.map → chunk-6572EFE4.js.map} +0 -0
- /package/dist/{chunk-YMI27QPF.js.map → chunk-6BG5HCUP.js.map} +0 -0
- /package/dist/{chunk-QRECBCJM.js.map → chunk-6EXFJWII.js.map} +0 -0
- /package/dist/{chunk-74CBR5YE.js.map → chunk-6PNRUGOK.js.map} +0 -0
- /package/dist/{chunk-PUUEI4W3.js.map → chunk-6RJEY6TC.js.map} +0 -0
- /package/dist/{chunk-DLVIRJGK.js.map → chunk-727GL2YY.js.map} +0 -0
- /package/dist/{chunk-J2BTILRR.js.map → chunk-7FGYLFW6.js.map} +0 -0
- /package/dist/{chunk-MKDFYE2E.js.map → chunk-7IMWTFEG.js.map} +0 -0
- /package/dist/{chunk-FER6EVIY.js.map → chunk-7POKH54R.js.map} +0 -0
- /package/dist/{chunk-H6BX6WOW.js.map → chunk-7T26IH6W.js.map} +0 -0
- /package/dist/{chunk-R33SBMB7.js.map → chunk-7XQRVZZQ.js.map} +0 -0
- /package/dist/{chunk-NFCS5WYC.js.map → chunk-A3SPPXMC.js.map} +0 -0
- /package/dist/{chunk-DQPIEQGP.js.map → chunk-A7CWPDEH.js.map} +0 -0
- /package/dist/{chunk-3PM3M2Q6.js.map → chunk-AGOYVKTI.js.map} +0 -0
- /package/dist/{chunk-OBGOLHCP.js.map → chunk-AIQKZUPB.js.map} +0 -0
- /package/dist/{chunk-GSCGKJNK.js.map → chunk-AMYDHG3S.js.map} +0 -0
- /package/dist/{chunk-U4LTPFD2.js.map → chunk-APJPB6TX.js.map} +0 -0
- /package/dist/{chunk-SP44O3OU.js.map → chunk-APLGT5EI.js.map} +0 -0
- /package/dist/{chunk-M3HGBO2Y.js.map → chunk-ATNKMGLO.js.map} +0 -0
- /package/dist/{chunk-4O2XWOLZ.js.map → chunk-AVX4CZQ3.js.map} +0 -0
- /package/dist/{chunk-CXAN2FHF.js.map → chunk-B46MK44K.js.map} +0 -0
- /package/dist/{chunk-RMCLFSMX.js.map → chunk-BBKUPEGG.js.map} +0 -0
- /package/dist/{chunk-J2WY42FA.js.map → chunk-BES6OQE3.js.map} +0 -0
- /package/dist/{chunk-GU7T2S5N.js.map → chunk-BM2N26SH.js.map} +0 -0
- /package/dist/{chunk-HEGV4QMS.js.map → chunk-C3NS74PZ.js.map} +0 -0
- /package/dist/{chunk-752WXSDN.js.map → chunk-C56ABB5V.js.map} +0 -0
- /package/dist/{chunk-77SYIH6O.js.map → chunk-C6MATJQ5.js.map} +0 -0
- /package/dist/{chunk-KUE5BOQE.js.map → chunk-CRX47CO6.js.map} +0 -0
- /package/dist/{chunk-GTHCHCWW.js.map → chunk-D33KWZQJ.js.map} +0 -0
- /package/dist/{chunk-AH3DGOTK.js.map → chunk-D7E3BSCX.js.map} +0 -0
- /package/dist/{chunk-OJWDNNW3.js.map → chunk-DFR3TMTZ.js.map} +0 -0
- /package/dist/{chunk-WYGTAQMX.js.map → chunk-DICC75CU.js.map} +0 -0
- /package/dist/{chunk-736RUNIA.js.map → chunk-DJ2LMKKX.js.map} +0 -0
- /package/dist/{chunk-4F3AEJI6.js.map → chunk-DJI4D7PM.js.map} +0 -0
- /package/dist/{chunk-LVELUUK6.js.map → chunk-DSZUQL4W.js.map} +0 -0
- /package/dist/{chunk-MT2R57SF.js.map → chunk-DVF246BE.js.map} +0 -0
- /package/dist/{chunk-OI6VI6SU.js.map → chunk-DVOWBHWN.js.map} +0 -0
- /package/dist/{chunk-PZKHST7A.js.map → chunk-E2KPRSA4.js.map} +0 -0
- /package/dist/{chunk-EKJHOWTZ.js.map → chunk-E3LMLWEB.js.map} +0 -0
- /package/dist/{chunk-QURYQFDN.js.map → chunk-EDC7X7PW.js.map} +0 -0
- /package/dist/{chunk-HYEIA25Y.js.map → chunk-EDSMULHU.js.map} +0 -0
- /package/dist/{chunk-U6552Q3T.js.map → chunk-EQQOZ6DD.js.map} +0 -0
- /package/dist/{chunk-IFSXVU2S.js.map → chunk-ERBDQ2GY.js.map} +0 -0
- /package/dist/{chunk-IZXYFWA4.js.map → chunk-EWI73URG.js.map} +0 -0
- /package/dist/{chunk-N3FM4BNA.js.map → chunk-EZ6LFN33.js.map} +0 -0
- /package/dist/{chunk-4K64EKM7.js.map → chunk-F7YL6DPR.js.map} +0 -0
- /package/dist/{chunk-ICAMYP5M.js.map → chunk-FIGFXMUP.js.map} +0 -0
- /package/dist/{chunk-54U6ZBEX.js.map → chunk-FJRJK67G.js.map} +0 -0
- /package/dist/{chunk-E5KOWRDU.js.map → chunk-FLHB2NZT.js.map} +0 -0
- /package/dist/{chunk-D3PTVN2I.js.map → chunk-FUGGM76A.js.map} +0 -0
- /package/dist/{chunk-TDTD66BK.js.map → chunk-FXPZAZYT.js.map} +0 -0
- /package/dist/{chunk-KO3OHHY2.js.map → chunk-GAGAM4MT.js.map} +0 -0
- /package/dist/{chunk-TK5FWVZR.js.map → chunk-GESGH3HY.js.map} +0 -0
- /package/dist/{chunk-2VJOSU4H.js.map → chunk-GI4PWKXI.js.map} +0 -0
- /package/dist/{chunk-KFNZZ2N6.js.map → chunk-GJTEBAZ7.js.map} +0 -0
- /package/dist/{chunk-LTJFV2JI.js.map → chunk-GNCGEW7F.js.map} +0 -0
- /package/dist/{chunk-34NV52R3.js.map → chunk-GOMUNPB6.js.map} +0 -0
- /package/dist/{chunk-LIJNVIT3.js.map → chunk-GUMUILEI.js.map} +0 -0
- /package/dist/{chunk-7NLF35YL.js.map → chunk-GVGNHBFT.js.map} +0 -0
- /package/dist/{chunk-K3D7IQQP.js.map → chunk-GW4YI3FB.js.map} +0 -0
- /package/dist/{chunk-D5TIVCXG.js.map → chunk-GXKCV7X7.js.map} +0 -0
- /package/dist/{chunk-2J77TWGH.js.map → chunk-H467EQA6.js.map} +0 -0
- /package/dist/{chunk-3OK7Y6ES.js.map → chunk-HE77VDDR.js.map} +0 -0
- /package/dist/{chunk-UO35OEOX.js.map → chunk-HT65RGCX.js.map} +0 -0
- /package/dist/{chunk-G6ICCGJ3.js.map → chunk-HVQSFTE7.js.map} +0 -0
- /package/dist/{chunk-G5UQBTXY.js.map → chunk-HXJPDC76.js.map} +0 -0
- /package/dist/{chunk-GIWFLWXG.js.map → chunk-I6LQW24C.js.map} +0 -0
- /package/dist/{chunk-467WDSOK.js.map → chunk-I7A6S5YL.js.map} +0 -0
- /package/dist/{chunk-AAS7OWV6.js.map → chunk-IADS4ZYD.js.map} +0 -0
- /package/dist/{chunk-Y3XZEKDQ.js.map → chunk-IJWMWCGR.js.map} +0 -0
- /package/dist/{chunk-SGH7I7OY.js.map → chunk-IWFO6KOU.js.map} +0 -0
- /package/dist/{chunk-GMHIOYB7.js.map → chunk-IYC6QGV2.js.map} +0 -0
- /package/dist/{chunk-3NNAC43A.js.map → chunk-J5AODKJO.js.map} +0 -0
- /package/dist/{chunk-DIP7YALH.js.map → chunk-JKI3LMLH.js.map} +0 -0
- /package/dist/{chunk-IJR6VOLU.js.map → chunk-JSYRWOCE.js.map} +0 -0
- /package/dist/{chunk-CEMSIU4Z.js.map → chunk-JTQTWO4D.js.map} +0 -0
- /package/dist/{chunk-BASI553K.js.map → chunk-KBTKAAHM.js.map} +0 -0
- /package/dist/{chunk-OYOFPNLC.js.map → chunk-KD7VEMWY.js.map} +0 -0
- /package/dist/{chunk-3DRLCX5V.js.map → chunk-KPGFGRSA.js.map} +0 -0
- /package/dist/{chunk-PLYVGZIN.js.map → chunk-KWFDEJFI.js.map} +0 -0
- /package/dist/{chunk-FNXCFIPW.js.map → chunk-KYLEH4OF.js.map} +0 -0
- /package/dist/{chunk-WXF2RTS4.js.map → chunk-L7FJTFJN.js.map} +0 -0
- /package/dist/{chunk-KI46GKMD.js.map → chunk-L7VVQOSY.js.map} +0 -0
- /package/dist/{chunk-O2UPPN5M.js.map → chunk-LKLQVANM.js.map} +0 -0
- /package/dist/{chunk-YNTLWCF4.js.map → chunk-LLYEAZ4E.js.map} +0 -0
- /package/dist/{chunk-4Z5X7PLC.js.map → chunk-LWM7JUW6.js.map} +0 -0
- /package/dist/{chunk-CHU3RDV4.js.map → chunk-LXKV4ND3.js.map} +0 -0
- /package/dist/{chunk-AB5IW227.js.map → chunk-LYLICEQO.js.map} +0 -0
- /package/dist/{chunk-OTW25A6I.js.map → chunk-M5GRI5K4.js.map} +0 -0
- /package/dist/{chunk-X2QJXDE4.js.map → chunk-MF65PKKF.js.map} +0 -0
- /package/dist/{chunk-EDDKPIIV.js.map → chunk-MJ4XIOPM.js.map} +0 -0
- /package/dist/{chunk-FLWQJDJ5.js.map → chunk-MMPJJQG3.js.map} +0 -0
- /package/dist/{chunk-T67LTMSW.js.map → chunk-MOU54FGD.js.map} +0 -0
- /package/dist/{chunk-LQKVNREV.js.map → chunk-NAWHQ4IL.js.map} +0 -0
- /package/dist/{chunk-ZBHGNE2J.js.map → chunk-NBHBB2VV.js.map} +0 -0
- /package/dist/{chunk-U5UGM5XD.js.map → chunk-NMOZDAEZ.js.map} +0 -0
- /package/dist/{chunk-D74Z2N4K.js.map → chunk-NZA4R3BE.js.map} +0 -0
- /package/dist/{chunk-WRMUXZ7C.js.map → chunk-OB2CX7PJ.js.map} +0 -0
- /package/dist/{chunk-YJSCLGAW.js.map → chunk-OB4I4OIT.js.map} +0 -0
- /package/dist/{chunk-DWJ6J3YW.js.map → chunk-OKQW2FPL.js.map} +0 -0
- /package/dist/{chunk-2GCHGWNE.js.map → chunk-ORLX6A3C.js.map} +0 -0
- /package/dist/{chunk-EBTUPRRQ.js.map → chunk-P5N4EYFW.js.map} +0 -0
- /package/dist/{chunk-JKL5S7UQ.js.map → chunk-PL4JE3NI.js.map} +0 -0
- /package/dist/{chunk-OP2GD6QW.js.map → chunk-PNUHKDY2.js.map} +0 -0
- /package/dist/{chunk-MZY3VKKM.js.map → chunk-PWJE7D6V.js.map} +0 -0
- /package/dist/{chunk-RISUROBM.js.map → chunk-PYE27I6J.js.map} +0 -0
- /package/dist/{chunk-R5QAL43H.js.map → chunk-QIJHK6P4.js.map} +0 -0
- /package/dist/{chunk-AJBDAVX3.js.map → chunk-QK3A23NP.js.map} +0 -0
- /package/dist/{chunk-CYDXCILL.js.map → chunk-QLWDNAOV.js.map} +0 -0
- /package/dist/{chunk-BQYRZIZ7.js.map → chunk-QS6DQBVJ.js.map} +0 -0
- /package/dist/{chunk-3PZ3LRPV.js.map → chunk-QSUVFPG3.js.map} +0 -0
- /package/dist/{chunk-PYB4BFEC.js.map → chunk-QUC5MLTN.js.map} +0 -0
- /package/dist/{chunk-WDASYY4S.js.map → chunk-QVT5AWPI.js.map} +0 -0
- /package/dist/{chunk-K4DQS2ML.js.map → chunk-QZC6WCBR.js.map} +0 -0
- /package/dist/{chunk-HWVPLFIW.js.map → chunk-RAHNICPP.js.map} +0 -0
- /package/dist/{chunk-H6MJFMHZ.js.map → chunk-RME6RGIW.js.map} +0 -0
- /package/dist/{chunk-XMBOLFFS.js.map → chunk-RQIB2F53.js.map} +0 -0
- /package/dist/{chunk-OXQ2SXVC.js.map → chunk-RUA72NQY.js.map} +0 -0
- /package/dist/{chunk-UMX6DZME.js.map → chunk-SCJHWN4X.js.map} +0 -0
- /package/dist/{chunk-HTMQGS63.js.map → chunk-SIXBDT5F.js.map} +0 -0
- /package/dist/{chunk-ZAX4XQLN.js.map → chunk-SPK3T4JK.js.map} +0 -0
- /package/dist/{chunk-WTSQUCHB.js.map → chunk-SSN2YSST.js.map} +0 -0
- /package/dist/{chunk-5MIBQ4P5.js.map → chunk-SYJCDX5V.js.map} +0 -0
- /package/dist/{chunk-ZR5EKJT6.js.map → chunk-T6276OXI.js.map} +0 -0
- /package/dist/{chunk-DEHLWZSI.js.map → chunk-T7OARG4N.js.map} +0 -0
- /package/dist/{chunk-77BHKC43.js.map → chunk-TF5L3BEV.js.map} +0 -0
- /package/dist/{chunk-GOCODNQS.js.map → chunk-TF6Z7BOP.js.map} +0 -0
- /package/dist/{chunk-WIFDNUKD.js.map → chunk-TJDXWZMO.js.map} +0 -0
- /package/dist/{chunk-SFIXTOOJ.js.map → chunk-TL5ATBHZ.js.map} +0 -0
- /package/dist/{chunk-XZCCEKPW.js.map → chunk-TMOHIOMT.js.map} +0 -0
- /package/dist/{chunk-AVXDIRRW.js.map → chunk-UI5X63YC.js.map} +0 -0
- /package/dist/{chunk-6QK65ZWM.js.map → chunk-UIY7BDZC.js.map} +0 -0
- /package/dist/{chunk-VATYK3JQ.js.map → chunk-UMBFMEO7.js.map} +0 -0
- /package/dist/{chunk-UU5FBVRX.js.map → chunk-UU5G7OA4.js.map} +0 -0
- /package/dist/{chunk-EGKARC53.js.map → chunk-UZUCYCF4.js.map} +0 -0
- /package/dist/{chunk-LPKJ77EK.js.map → chunk-V2A7G7S7.js.map} +0 -0
- /package/dist/{chunk-CH4UQ4NO.js.map → chunk-V5G4TKRC.js.map} +0 -0
- /package/dist/{chunk-UBRQ3PQD.js.map → chunk-VKAVW34W.js.map} +0 -0
- /package/dist/{chunk-JV5ULONH.js.map → chunk-VVLEVNTQ.js.map} +0 -0
- /package/dist/{chunk-44JWVYJB.js.map → chunk-VW7X7TWZ.js.map} +0 -0
- /package/dist/{chunk-3CDJSKDW.js.map → chunk-VWA2CHSL.js.map} +0 -0
- /package/dist/{chunk-IN3VQFKS.js.map → chunk-W43HZPM7.js.map} +0 -0
- /package/dist/{chunk-SXGJL7UT.js.map → chunk-WHGD7Q2L.js.map} +0 -0
- /package/dist/{chunk-XOIDUM2H.js.map → chunk-WNXKYEVN.js.map} +0 -0
- /package/dist/{chunk-TKQL7EDB.js.map → chunk-WSA7UBX4.js.map} +0 -0
- /package/dist/{chunk-AJDGP2N4.js.map → chunk-WZ5TQJ3T.js.map} +0 -0
- /package/dist/{chunk-FBA2NXYH.js.map → chunk-X3TGNSOG.js.map} +0 -0
- /package/dist/{chunk-R4JA5JFI.js.map → chunk-X4WXYI3N.js.map} +0 -0
- /package/dist/{chunk-Q5EZNBPI.js.map → chunk-XIQ3AIAJ.js.map} +0 -0
- /package/dist/{chunk-S27VZ5DO.js.map → chunk-XWYT4LEL.js.map} +0 -0
- /package/dist/{chunk-477DTTMH.js.map → chunk-Y3PU75OC.js.map} +0 -0
- /package/dist/{chunk-4JXPLTWV.js.map → chunk-Y5ZWX5YS.js.map} +0 -0
- /package/dist/{chunk-4BWMAGJJ.js.map → chunk-YA5PABND.js.map} +0 -0
- /package/dist/{chunk-OGU73VUN.js.map → chunk-YBPRR2QS.js.map} +0 -0
- /package/dist/{chunk-TNSJFZ6Q.js.map → chunk-YDYR7XQE.js.map} +0 -0
- /package/dist/{chunk-GTRAH4FG.js.map → chunk-YG6V2LQH.js.map} +0 -0
- /package/dist/{chunk-XVLEBB4Y.js.map → chunk-YUXA7ALE.js.map} +0 -0
- /package/dist/{chunk-SN2WENRP.js.map → chunk-YWHQDXPB.js.map} +0 -0
- /package/dist/{chunk-BFFNINCC.js.map → chunk-YWRR5R7B.js.map} +0 -0
- /package/dist/{chunk-FSDQQQIA.js.map → chunk-YYRK7A4N.js.map} +0 -0
- /package/dist/{chunk-MRECRNVU.js.map → chunk-Z26CDLUV.js.map} +0 -0
- /package/dist/{chunk-OYCK4JRS.js.map → chunk-Z27EXLMQ.js.map} +0 -0
- /package/dist/{chunk-UTRNLNCW.js.map → chunk-Z7GDH7W2.js.map} +0 -0
- /package/dist/{chunk-PRT4J2DL.js.map → chunk-ZGVLSAWL.js.map} +0 -0
- /package/dist/{chunk-OK7BQMCI.js.map → chunk-ZM6Q5NQN.js.map} +0 -0
- /package/dist/{computer-viewer-5LKRCEVQ.js.map → computer-viewer-SROXREYD.js.map} +0 -0
- /package/dist/{embedded-new-voice-GHJRY3YL.js.map → embedded-new-voice-EIQY2VBF.js.map} +0 -0
- /package/dist/{embedded-voice-ASQXBSTX.js.map → embedded-voice-LMWNH7F7.js.map} +0 -0
- /package/dist/{fleet-decision-row-U7LDVBEM.js.map → fleet-decision-row-X2G56ZRA.js.map} +0 -0
- /package/dist/{latest-question-RNVF262Q.js.map → latest-question-KA7AQYVI.js.map} +0 -0
- /package/dist/{model-policy-picker-menu-E6XKMFTA.js.map → model-policy-picker-menu-SHWPT5VA.js.map} +0 -0
- /package/dist/{payment-page-card-DJDKV2LW.js.map → payment-page-card-NNVUISN4.js.map} +0 -0
- /package/dist/{platform-activity-row-MSDCSMET.js.map → platform-activity-row-7UDWSAHK.js.map} +0 -0
- /package/dist/{queue-surface-implementation-GUAIG6TK.js.map → queue-surface-implementation-BUXSO24N.js.map} +0 -0
- /package/dist/{recorder-host-2MYDJPQW.js.map → recorder-host-POX54CFT.js.map} +0 -0
- /package/dist/{sandbox-files-W5W2LW4K.js.map → sandbox-files-33QD7DW2.js.map} +0 -0
- /package/dist/{session-connect-cards-HPH7JOZP.js.map → session-connect-cards-CXGNVA2A.js.map} +0 -0
- /package/dist/{session-realtime-SDTKFFIR.js.map → session-realtime-CVDSEULB.js.map} +0 -0
- /package/dist/{timeline-annotation-markers-FNILLWNU.js.map → timeline-annotation-markers-5J5TM5IP.js.map} +0 -0
- /package/dist/{timeline-annotation-selection-MBCIDO2Q.js.map → timeline-annotation-selection-WLY7FB7F.js.map} +0 -0
- /package/dist/{timeline-annotations-dialog-JPNKLOTE.js.map → timeline-annotations-dialog-67VRFKJU.js.map} +0 -0
package/dist/meetings.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/meetings/recorder-panel.tsx","../src/meetings/live-transcript.tsx","../src/meetings/meeting-transcript.tsx","../src/meetings/overlay-scope.tsx","../src/meetings/meetings-list-page.tsx","../src/meetings/delete-meeting-dialog.tsx","../src/meetings/meeting-detail-page.tsx","../src/meetings/meeting-player.tsx","../src/meetings/meeting-ask.tsx","../src/meetings/sticky-bar-edge.tsx","../src/meetings/meeting-mentions.tsx","../src/meetings/meeting-notes.tsx","../src/meetings/meeting-settings.tsx"],"sourcesContent":["/**\n * The recorder on the Meetings page. Idle, it is one row: a title, whether to\n * include the other people (other apps' audio in the desktop app, a tab's audio\n * in a browser), and Start recording. Live, the same panel shows the\n * clock, a level meter per track, Pause and Stop, and where the audio is (on\n * this device, uploading, or waiting for the connection).\n */\nimport { useOpenGeniText, createOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\nimport {\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n type ComponentProps,\n} from \"react\";\nimport {\n ChevronDownIcon,\n CircleIcon,\n InfoIcon,\n LanguagesIcon,\n MicIcon,\n NotebookPenIcon,\n PauseIcon,\n PencilIcon,\n PlayIcon,\n SquareIcon,\n} from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\n\nimport { Button } from \"../ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuNote,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"../ui/dropdown-menu\";\nimport { Checkbox } from \"../ui/field\";\nimport { Input } from \"../ui/input\";\nimport { Notice } from \"../ui/notice\";\nimport { cn } from \"../app/lib/utils\";\n\nimport { formatClock, ownerLiveLaneName } from \"../recordings\";\nimport type { MeetingRecorder } from \"./recorder-context\";\nimport { canStartRecording } from \"./recorder-state\";\nimport { LiveTranscript, liveStatus, type LiveTranscriptLine } from \"./live-transcript\";\nimport { DETECT_LANGUAGE, meetingLanguageOptions } from \"./meeting-languages\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\n\nconst defaultText = createOpenGeniText();\n\ntype RecorderError = NonNullable<MeetingRecorder[\"error\"]>;\n\n/** What went wrong and what to do, in the browser's terms. */\nexport function recorderErrorText(\n error: RecorderError,\n systemAudioKind: MeetingRecorder[\"systemAudioKind\"] = \"display\",\n msg: OpenGeniText = defaultText,\n): { title: string; body: string } {\n if (systemAudioKind === \"desktop\" && error.code === \"system_audio_unavailable\") {\n return desktopSystemAudioErrorText(error.reason, msg);\n }\n switch (error.code) {\n case \"microphone_denied\":\n return {\n title: msg(\"meetings.recorderPanel.microphoneBlocked\"),\n body:\n systemAudioKind === \"desktop\"\n ? msg(\"meetings.recorderPanel.allowThisAppToUse\")\n : msg(\"meetings.recorderPanel.allowMicrophoneAccessForThis\"),\n };\n case \"microphone_unavailable\":\n return {\n title: msg(\"meetings.recorderPanel.noMicrophoneFound\"),\n body: msg(\"meetings.recorderPanel.connectAMicrophoneOrCheck\"),\n };\n case \"system_audio_not_shared\":\n return {\n title: msg(\"meetings.recorderPanel.theTabSAudioWasn\"),\n body: msg(\"meetings.recorderPanel.whenYourBrowserAsksWhat\"),\n };\n case \"system_audio_unavailable\":\n return {\n title: msg(\"meetings.recorderPanel.canTRecordATab\"),\n body: msg(\"meetings.recorderPanel.thisBrowserCanTShare\"),\n };\n case \"unsupported\":\n return {\n title: msg(\"meetings.recorderPanel.thisBrowserCanTRecord\"),\n body: msg(\"meetings.recorderPanel.useACurrentVersionOf\"),\n };\n case \"upload_failed\":\n return {\n title: msg(\"meetings.recorderPanel.uploadStopped\"),\n body: msg(\"meetings.recorderPanel.uploadfailurereasonTheRecordingIsSaved\", {\n uploadFailureReason: uploadFailureReason(error.message, msg),\n }),\n };\n default:\n return { title: msg(\"meetings.recorderPanel.recordingStopped\"), body: error.message };\n }\n}\n\n/** Why the desktop app couldn't record computer audio, and what to do on this computer. */\nfunction desktopSystemAudioErrorText(\n reason: RecorderError[\"reason\"],\n msg: OpenGeniText,\n): { title: string; body: string } {\n const title = msg(\"meetings.recorderPanel.canTRecordComputerAudio\");\n switch (reason) {\n case \"permission_denied\":\n return {\n title: msg(\"meetings.recorderPanel.computerAudioIsnTAllowed\"),\n body: msg(\"meetings.recorderPanel.allowThisAppToRecordComputerAudio\"),\n };\n case \"sound_server_unavailable\":\n return { title, body: msg(\"meetings.recorderPanel.noSoundServerIsRunning\") };\n case \"unavailable\":\n return { title, body: msg(\"meetings.recorderPanel.thisComputerCanTRecordItsOwnAudio\") };\n default:\n return { title, body: msg(\"meetings.recorderPanel.computerAudioDidnTStart\") };\n }\n}\n\n/** Why the server refused the audio, as a sentence; the server's own words when it's not a known case. */\nexport function uploadFailureReason(message: string, msg: OpenGeniText = defaultText): string {\n const text = message.trim();\n if (/not.?found|\\b404\\b/i.test(text)) {\n return msg(\"meetings.recorderPanel.theMeetingWasDeletedOr\");\n }\n if (/forbidden|permission|\\b403\\b/i.test(text)) {\n return msg(\"meetings.recorderPanel.youNoLongerHavePermission\");\n }\n if (/too large|\\b413\\b/i.test(text)) return msg(\"meetings.recorderPanel.aPieceOfTheAudio\");\n if (/usage allowance|\\b402\\b/i.test(text)) {\n return msg(\"meetings.recorderPanel.theUsageAllowanceIsUsed\");\n }\n if (!text) return msg(\"meetings.recorderPanel.theServerRefusedTheAudio\");\n return msg(\"meetings.recorderPanel.theServerRefusedTheAudio2\", {\n value: text.replace(/[.\\s]+$/, \"\"),\n });\n}\n\n/** Where the audio is right now, in one short line. */\nexport function uploadLine(\n recorder: MeetingRecorder,\n online: boolean,\n msg: OpenGeniText = defaultText,\n): string | null {\n const upload = recorder.upload;\n const capturing = recorder.state === \"recording\" || recorder.state === \"paused\";\n if (upload?.failed)\n return msg(\"meetings.recorderPanel.uploadFailedMessage\", { message: upload.failed.message });\n if (upload?.finalized) return msg(\"meetings.recorderPanel.uploaded\");\n if (upload?.discarded) return msg(\"meetings.recorderPanel.nothingWasRecordedSoNo\");\n if (!online || upload?.retryingAfterError) {\n return capturing\n ? msg(\"meetings.recorderPanel.notUploadingNoConnectionRecording\")\n : msg(\"meetings.recorderPanel.notUploadingNoConnectionThe\");\n }\n if (recorder.state === \"paused\")\n return msg(\"meetings.recorderPanel.nothingIsRecordedWhilePaused\");\n if (capturing) {\n // In a browser, closing the tab ends the recording; an app keeps recording.\n return recorder.systemAudioKind === \"desktop\"\n ? capturingWhat(recorder, msg)\n : msg(\"meetings.recorderPanel.capturingwhatValue\", {\n capturingWhat: capturingWhat(recorder, msg),\n value: msg(\"meetings.recorderPanel.youCanUseOtherPages\"),\n });\n }\n if (!upload || recorder.state === \"starting\") return null;\n // After Stop: the audio uploaded while it recorded, so usually only its end\n // is left; after a dropped connection it can be more.\n return msg(\"meetings.recorderPanel.savingTheRestOfTheAudio\");\n}\n\n/** What this recording captures, as a sentence. */\nfunction capturingWhat(recorder: MeetingRecorder, msg: OpenGeniText = defaultText): string {\n const sources = new Set(recorder.tracks.map((track) => track.source));\n const system = sources.has(\"system\");\n if (!sources.has(\"microphone\")) {\n return system\n ? recorder.systemAudioKind === \"desktop\"\n ? msg(\"meetings.recorderPanel.recordingYourComputerSAudio\")\n : msg(\"meetings.recorderPanel.recordingTheTabSAudio\")\n : msg(\"meetings.recorderPanel.recording\");\n }\n return system\n ? recorder.systemAudioKind === \"desktop\"\n ? msg(\"meetings.recorderPanel.recordingYourMicrophoneAndComputerAudio\")\n : msg(\"meetings.recorderPanel.recordingYourMicrophoneAndTabAudio\")\n : msg(\"meetings.recorderPanel.recordingYourMicrophoneOnly\");\n}\n\n/** True while audio is waiting on this device because the connection is down. */\nexport function uploadStalled(recorder: MeetingRecorder, online: boolean): boolean {\n const upload = recorder.upload;\n if (upload?.failed || upload?.finalized || upload?.discarded) return false;\n return !online || Boolean(upload?.retryingAfterError);\n}\n\n/** Whether the browser says it's online, kept current. */\nexport function useOnline(): boolean {\n const [online, setOnline] = useState(() =>\n typeof navigator === \"undefined\" ? true : navigator.onLine,\n );\n useEffect(() => {\n const update = () => setOnline(navigator.onLine);\n window.addEventListener(\"online\", update);\n window.addEventListener(\"offline\", update);\n return () => {\n window.removeEventListener(\"online\", update);\n window.removeEventListener(\"offline\", update);\n };\n }, []);\n return online;\n}\n\n/** A level bar fed from the analyser every frame, without re-rendering React. */\nfunction LevelMeter({\n recorder,\n trackNumber,\n label,\n paused,\n}: {\n recorder: MeetingRecorder;\n trackNumber: number;\n label: string;\n paused: boolean;\n}) {\n const barRef = useRef<HTMLSpanElement>(null);\n const levels = recorder.levels;\n useEffect(() => {\n let frame = 0;\n let smoothed = 0;\n const tick = () => {\n const level = paused ? 0 : (levels()[trackNumber] ?? 0);\n // Fast attack, slow release, so speech reads as steady movement.\n smoothed = level > smoothed ? level : smoothed * 0.88 + level * 0.12;\n if (barRef.current) barRef.current.style.transform = `scaleX(${Math.max(0.02, smoothed)})`;\n frame = requestAnimationFrame(tick);\n };\n frame = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(frame);\n }, [levels, trackNumber, paused]);\n return (\n // Label and bar are cells of the parent grid, so every label fits its\n // column and the bars line up.\n <div className=\"contents\">\n <span className=\"min-w-0 max-w-44 truncate text-xs leading-4 text-fg-muted\" title={label}>\n {label}\n </span>\n <span aria-hidden=\"true\" className=\"relative h-1.5 overflow-hidden rounded-full bg-surface-2\">\n <span\n ref={barRef}\n className=\"absolute inset-0 origin-left rounded-full bg-status-idle transition-transform duration-75 motion-reduce:transition-none\"\n style={{ transform: \"scaleX(0.02)\" }}\n />\n </span>\n </div>\n );\n}\n\nfunction trackLabel(\n source: string,\n systemAudioKind: MeetingRecorder[\"systemAudioKind\"],\n msg: OpenGeniText = defaultText,\n): string {\n if (source === \"microphone\") return msg(\"meetings.recorderPanel.microphone\");\n if (source === \"system\")\n return systemAudioKind === \"desktop\"\n ? msg(\"meetings.recorderPanel.computerAudio\")\n : msg(\"meetings.recorderPanel.tabAudio\");\n return msg(\"meetings.recorderPanel.audio\");\n}\n\n/**\n * Who a track's live text is from. Beside computer or tab audio the\n * microphone is the person recording (`ownerName`, else \"You\") and the other\n * track is \"Others\". A microphone alone may pick up a whole room, so it is\n * named like its level meter.\n */\nexport function liveSpeakerName(\n recorder: Pick<MeetingRecorder, \"tracks\" | \"systemAudioKind\">,\n trackNumber: number,\n msg: OpenGeniText = defaultText,\n ownerName?: string | null,\n): string {\n const owned = ownerLiveLaneName(\n recorder.tracks,\n trackNumber,\n ownerName?.trim() || msg(\"meetings.liveTranscript.you\"),\n msg,\n );\n if (owned) return owned;\n const source = recorder.tracks.find((track) => track.trackNumber === trackNumber)?.source;\n return trackLabel(source ?? \"\", recorder.systemAudioKind, msg);\n}\n\n/** The live text the recorder has heard, as lines for {@link LiveTranscript}. */\nexport function recorderLiveLines(recorder: Pick<MeetingRecorder, \"live\">): LiveTranscriptLine[] {\n return (recorder.live ?? []).flatMap((track) => track.segments);\n}\n\n/** Why live text stopped, in the recorder's terms, from the first track's reason. */\nexport function liveUnavailableText(\n tracks: readonly { error: { code: string; message: string } | null }[],\n msg: OpenGeniText = defaultText,\n): string {\n const code = tracks.find((track) => track.error)?.error?.code;\n const reason =\n code === \"quota_exceeded\"\n ? msg(\"meetings.recorderPanel.theLiveTranscriptionAccountHas\")\n : code === \"auth_error\"\n ? msg(\"meetings.recorderPanel.theLiveTranscriptionProviderRefused\")\n : code === \"credential_unavailable\"\n ? msg(\"meetings.recorderPanel.noLiveTranscriptionProviderIs\")\n : code === \"rate_limited\" || code === \"resource_exhausted\" || code === \"queue_overflow\"\n ? msg(\"meetings.recorderPanel.theLiveTranscriptionProviderIs\")\n : null;\n return msg(\"meetings.recorderPanel.liveTextIsnTAvailable\", { value: reason ? ` ${reason}` : \"\" });\n}\n\n/** The meeting's name while it records, and renaming it without stopping. */\nfunction RecordingTitle({ recorder }: { recorder: MeetingRecorder }) {\n const msg = useOpenGeniText();\n const inputId = useId();\n const [editing, setEditing] = useState(false);\n const [draft, setDraft] = useState(\"\");\n const [saving, setSaving] = useState(false);\n const title = recorder.title?.trim() || null;\n if (editing) {\n const save = async () => {\n const next = draft.trim();\n if (!next || next === title) {\n setEditing(false);\n return;\n }\n setSaving(true);\n try {\n await recorder.rename(next);\n setEditing(false);\n } catch (error) {\n toast.error(msg(\"meetings.recorderPanel.couldnTRenameThisMeeting\"), {\n description: error instanceof Error ? userErrorText(error) : undefined,\n });\n } finally {\n setSaving(false);\n }\n };\n return (\n <form\n className=\"mb-4 flex items-center gap-2 max-sm:flex-wrap\"\n onSubmit={(event) => {\n event.preventDefault();\n void save();\n }}\n >\n <label htmlFor={inputId} className=\"sr-only\">\n {msg(\"meetings.recorderPanel.meetingTitle\")}\n </label>\n <Input\n id={inputId}\n autoFocus\n value={draft}\n maxLength={300}\n placeholder={msg(\"meetings.recorderPanel.nameThisMeeting\")}\n disabled={saving}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") setEditing(false);\n }}\n className=\"h-9 min-w-0 flex-1 max-sm:basis-full\"\n />\n <Button type=\"submit\" size=\"sm\" disabled={saving} className=\"pointer-coarse:h-11\">\n {saving ? msg(\"meetings.recorderPanel.saving\") : msg(\"meetings.recorderPanel.save\")}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n disabled={saving}\n onClick={() => setEditing(false)}\n className=\"pointer-coarse:h-11\"\n >\n {msg(\"meetings.recorderPanel.cancel\")}\n </Button>\n </form>\n );\n }\n return (\n <div className=\"mb-4 flex min-w-0 items-center gap-1\">\n <p\n className={cn(\n \"min-w-0 truncate text-sm leading-5 font-medium\",\n title ? \"text-fg\" : \"text-fg-muted\",\n )}\n >\n {title ?? msg(\"meetings.recorderPanel.namedForYou\")}\n </p>\n <Button\n type=\"button\"\n size=\"xs\"\n variant=\"ghost\"\n onClick={() => {\n setDraft(title ?? \"\");\n setEditing(true);\n }}\n className=\"shrink-0 text-fg-label pointer-coarse:h-11\"\n >\n <PencilIcon aria-hidden=\"true\" />\n {title ? msg(\"meetings.recorderPanel.rename\") : msg(\"meetings.recorderPanel.nameIt\")}\n </Button>\n </div>\n );\n}\n\nfunction RecorderLiveTranscript({\n recorder,\n viewerName,\n}: {\n recorder: MeetingRecorder;\n viewerName: string | null;\n}) {\n const msg = useOpenGeniText();\n const live = recorder.live;\n const lines = useMemo(() => recorderLiveLines({ live: live ?? null }), [live]);\n if (!live || live.length === 0) return null;\n const status = liveStatus(live, msg);\n if (lines.length === 0 && live.every((track) => track.state === \"unavailable\")) {\n // Nothing to read, so no empty box: one line says it and that nothing is lost.\n return (\n <p\n className=\"mt-3 flex items-start gap-2 rounded-[10px] border border-border bg-surface-2/60 px-3 py-2 text-xs leading-4.5 text-fg-label\"\n aria-live=\"polite\"\n >\n <InfoIcon aria-hidden=\"true\" className=\"mt-0.5 size-3.5 shrink-0 text-fg-muted\" />\n {liveUnavailableText(live, msg)}\n </p>\n );\n }\n return (\n <LiveTranscript\n className=\"mt-4 border-t border-border pt-4\"\n lines={lines}\n partials={live.map((track) => ({ trackNumber: track.trackNumber, text: track.partial }))}\n tracks={recorder.tracks}\n speakerName={(trackNumber) => liveSpeakerName(recorder, trackNumber, msg, viewerName)}\n status={status}\n empty={\n recorder.state === \"paused\"\n ? msg(\"meetings.recorderPanel.pausedNothingIsHeardUntil\")\n : msg(\"meetings.recorderPanel.listeningWhatSSaidShows\")\n }\n />\n );\n}\n\n/** The pulsing dot, the state in a word and the clock of a recording under way. */\nfunction RecordingClock({ recorder, stalled }: { recorder: MeetingRecorder; stalled: boolean }) {\n const msg = useOpenGeniText();\n const paused = recorder.state === \"paused\";\n return (\n <div className=\"flex min-w-0 items-center gap-3\">\n <span className=\"relative flex size-3 shrink-0\" aria-hidden=\"true\">\n {!paused ? (\n <span\n className={cn(\n \"absolute inset-0 animate-ping rounded-full motion-reduce:animate-none\",\n stalled ? \"bg-status-waiting/60\" : \"bg-status-failed/60\",\n )}\n />\n ) : null}\n <span\n className={cn(\n \"relative size-3 rounded-full\",\n paused ? \"bg-fg-subtle\" : stalled ? \"bg-status-waiting\" : \"bg-status-failed\",\n )}\n />\n </span>\n <div className=\"min-w-0\">\n <p className=\"text-sm leading-5 font-medium text-fg\">\n {recorder.state === \"stopping\"\n ? msg(\"meetings.recorderPanel.finishing\")\n : paused\n ? msg(\"meetings.recorderPanel.paused\")\n : stalled\n ? msg(\"meetings.recorderPanel.recordingNotUploading\")\n : msg(\"meetings.recorderPanel.recording2\")}\n </p>\n <p\n className=\"text-2xl leading-8 font-semibold tracking-[-0.5px] text-fg tabular-nums\"\n role=\"timer\"\n aria-live=\"off\"\n >\n {formatClock(recorder.elapsedMilliseconds)}\n </p>\n </div>\n </div>\n );\n}\n\n/** Pause or Resume, and Stop. */\nfunction RecordingControls({\n recorder,\n onStopped,\n}: {\n recorder: MeetingRecorder;\n onStopped?: ((recordingId: string) => void) | undefined;\n}) {\n const msg = useOpenGeniText();\n const paused = recorder.state === \"paused\";\n const stopping = recorder.state === \"stopping\";\n const recordingId = recorder.recordingId;\n return (\n <>\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={stopping}\n onClick={() => (paused ? recorder.resume() : recorder.pause())}\n className=\"rounded-[10px] pointer-coarse:h-11 max-sm:flex-1\"\n >\n {paused ? <PlayIcon aria-hidden=\"true\" /> : <PauseIcon aria-hidden=\"true\" />}\n {paused ? msg(\"meetings.recorderPanel.resume\") : msg(\"meetings.recorderPanel.pause\")}\n </Button>\n <Button\n type=\"button\"\n disabled={stopping}\n onClick={() => {\n void recorder.stop().then(() => {\n if (recordingId) onStopped?.(recordingId);\n });\n }}\n className=\"rounded-[10px] pointer-coarse:h-11 max-sm:flex-1\"\n >\n <SquareIcon aria-hidden=\"true\" className=\"fill-current\" />\n {msg(\"meetings.recorderPanel.stop\")}\n </Button>\n </>\n );\n}\n\n/**\n * The recording on the meeting's own page while this device records it, so\n * taking notes there never hides that it is still recording or how to end it:\n * the state and clock with Pause and Stop. Says so only when the connection\n * keeps the audio on this device.\n */\nexport function RecordingBar({\n recorder,\n onStopped,\n}: {\n recorder: MeetingRecorder;\n /** After Stop, with the recording that stopped. */\n onStopped?: ((recordingId: string) => void) | undefined;\n}) {\n const msg = useOpenGeniText();\n const online = useOnline();\n const stalled = uploadStalled(recorder, online);\n return (\n <section\n aria-label={msg(\"meetings.recorderPanel.recording2\")}\n className=\"rounded-[14px] border border-border bg-surface px-5 py-4 shadow-[0_1px_2px_rgb(0_0_0/0.04)] max-sm:p-4\"\n >\n <div className=\"flex flex-wrap items-center justify-between gap-x-6 gap-y-3\">\n <RecordingClock recorder={recorder} stalled={stalled} />\n <div className=\"flex shrink-0 items-center gap-2 max-sm:w-full\">\n <RecordingControls recorder={recorder} onStopped={onStopped} />\n </div>\n </div>\n {stalled ? (\n <p className=\"mt-3 text-xs leading-4.5 font-medium text-fg-label\" aria-live=\"polite\">\n {uploadLine(recorder, online, msg)}\n </p>\n ) : null}\n </section>\n );\n}\n\nfunction RecorderPanelContent({\n recorder,\n onStopped,\n onOpenNotes,\n liveTranscript = null,\n defaultLanguage,\n autoStart = null,\n externalRef = null,\n notice = null,\n viewerName = null,\n}: {\n /** Null while the capture code loads. */\n recorder: MeetingRecorder | null;\n /** After Stop, with the recording to open. */\n onStopped?: ((recordingId: string) => void) | undefined;\n /** Opens the meeting being recorded, where its notepad is. */\n onOpenNotes?: ((recordingId: string) => void) | undefined;\n /** Offer the live transcript preview; null when the workspace has no live model. */\n liveTranscript?: { defaultOn: boolean; usdPerHour?: number | null } | null;\n /**\n * The workspace's meeting language; null detects it. Undefined while it\n * isn't known: a meeting started then names no language, and the server\n * uses the workspace's.\n */\n defaultLanguage?: string | null | undefined;\n /**\n * Start recording as soon as the recorder is ready, with this panel's\n * defaults, as a desktop call notification asked. `take` returns the\n * request once, so it starts one recording.\n */\n autoStart?: {\n pending: boolean;\n take: () => { title: string; titleSource?: \"person\" | \"app\" } | null;\n } | null;\n /** The host's own id for what new recordings belong to, such as a project. */\n externalRef?: string | null | undefined;\n /** A short line shown before every start, such as a reminder to tell the people present. */\n notice?: ReactNode;\n /** The person recording's name, for their microphone's live text beside computer or tab audio. */\n viewerName?: string | null | undefined;\n}) {\n const msg = useOpenGeniText();\n const titleId = useId();\n const tabAudioId = useId();\n const [title, setTitle] = useState(\"\");\n const [languageChoice, setLanguage] = useState<string | null>(null);\n const language = languageChoice ?? defaultLanguage ?? DETECT_LANGUAGE;\n const desktopAudio = recorder?.systemAudioKind === \"desktop\";\n // In the desktop app computer audio is on unless turned off; a browser's\n // share prompt is something to opt into.\n const [tabAudioChoice, setTabAudio] = useState<boolean | null>(null);\n const tabAudio = tabAudioChoice ?? desktopAudio;\n const [liveChoice, setLiveChoice] = useState<boolean | null>(null);\n const liveOn = liveTranscript ? (liveChoice ?? liveTranscript.defaultOn) : false;\n const [errorDismissed, setErrorDismissed] = useState(false);\n const online = useOnline();\n const state = recorder?.state ?? \"idle\";\n const live = state === \"recording\" || state === \"paused\" || state === \"stopping\";\n\n /** `guess` is the app's name for the meeting, used only when nobody typed one. */\n const start = async (titleText: string = title, guess?: string) => {\n if (!recorder) return;\n setErrorDismissed(false);\n const name = titleText.trim();\n const guessed = guess?.trim();\n await recorder.start({\n // Unnamed, Opengeni names it: after the calendar event at the time, or\n // from the conversation once its notes are written.\n ...(name ? { title: name } : guessed ? { title: guessed, titleSource: \"app\" as const } : {}),\n systemAudio: tabAudio,\n ...(liveOn ? { liveTranscript: true } : {}),\n ...(externalRef ? { externalRef } : {}),\n // Names their microphone in the transcript when Opengeni has no name for them.\n ...(viewerName?.trim() ? { ownerName: viewerName } : {}),\n // Sent even when it's the workspace's, so this meeting keeps it.\n transcription:\n languageChoice === null && defaultLanguage === undefined\n ? {}\n : { language: language === DETECT_LANGUAGE ? null : language },\n });\n };\n // After an earlier recording stopped or failed too, as a click on Start would.\n const autoStartReady = Boolean(\n autoStart?.pending && recorder?.supported && canStartRecording(state),\n );\n const startRef = useRef(start);\n startRef.current = start;\n useEffect(() => {\n if (!autoStartReady) return;\n const request = autoStart?.take();\n if (!request) return;\n // The call app's name is a guess: a title already typed wins over it.\n if (request.titleSource === \"app\") {\n void startRef.current(undefined, request.title);\n return;\n }\n // A start without a title (the Start recording key) keeps one already typed, as the button does.\n if (request.title) setTitle(request.title);\n void startRef.current(request.title || undefined);\n }, [autoStart, autoStartReady]);\n\n if (recorder && !recorder.supported) {\n return (\n <Notice tone=\"muted\" title={msg(\"meetings.recorderPanel.thisBrowserCanTRecord\")}>\n {msg(\"meetings.recorderPanel.useACurrentVersionOf2\")}\n </Notice>\n );\n }\n\n if (recorder && live) {\n const stalled = uploadStalled(recorder, online);\n const recordingId = recorder.recordingId;\n const line = uploadLine(recorder, online, msg);\n return (\n <section\n aria-label={msg(\"meetings.recorderPanel.recording2\")}\n className=\"rounded-[14px] border border-border bg-surface p-5 shadow-[0_1px_2px_rgb(0_0_0/0.04)] max-sm:p-4\"\n >\n <RecordingTitle recorder={recorder} />\n <div className=\"flex flex-wrap items-center gap-x-6 gap-y-4\">\n <RecordingClock recorder={recorder} stalled={stalled} />\n <div className=\"grid min-w-48 flex-1 grid-cols-[minmax(0,max-content)_minmax(4rem,1fr)] items-center gap-x-3 gap-y-2\">\n {recorder.tracks.map((track) => (\n <LevelMeter\n key={track.trackNumber}\n recorder={recorder}\n trackNumber={track.trackNumber}\n label={trackLabel(track.source, recorder.systemAudioKind, msg)}\n paused={state === \"paused\"}\n />\n ))}\n </div>\n <div className=\"flex shrink-0 items-center gap-2 max-sm:w-full\">\n {onOpenNotes && recordingId && recorder.upload?.created ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={() => onOpenNotes(recordingId)}\n className=\"rounded-[10px] pointer-coarse:h-11 max-sm:flex-1\"\n >\n <NotebookPenIcon aria-hidden=\"true\" />\n {msg(\"meetings.recorderPanel.takeNotes\")}\n </Button>\n ) : null}\n <RecordingControls recorder={recorder} onStopped={onStopped} />\n </div>\n </div>\n {line ? (\n <p\n className={cn(\n \"mt-3 text-xs leading-4.5\",\n stalled ? \"font-medium text-fg-label\" : \"text-fg-muted\",\n )}\n aria-live=\"polite\"\n >\n {line}\n </p>\n ) : null}\n <RecorderLiveTranscript recorder={recorder} viewerName={viewerName} />\n </section>\n );\n }\n\n const starting = state === \"starting\";\n const error = recorder?.error && !errorDismissed ? recorder.error : null;\n const startHint = recorderHint(\n {\n desktopAudio,\n starting,\n tabAudio,\n systemAudioSupported: Boolean(recorder?.systemAudioSupported),\n },\n msg,\n );\n return (\n <section aria-label={msg(\"meetings.recorderPanel.newRecording\")} className=\"grid gap-3\">\n <form\n className=\"flex items-center gap-3 rounded-[14px] border border-border bg-surface p-2 pl-4 shadow-[0_1px_2px_rgb(0_0_0/0.04)] max-sm:flex-col max-sm:items-stretch max-sm:gap-2 max-sm:p-3\"\n onSubmit={(event) => {\n event.preventDefault();\n void start();\n }}\n >\n <MicIcon aria-hidden=\"true\" className=\"size-4 shrink-0 text-fg-subtle max-sm:hidden\" />\n <label htmlFor={titleId} className=\"sr-only\">\n {msg(\"meetings.recorderPanel.meetingTitle\")}\n </label>\n <Input\n id={titleId}\n value={title}\n maxLength={300}\n onChange={(event) => setTitle(event.target.value)}\n placeholder={msg(\"meetings.recorderPanel.nameThisMeetingOptional\")}\n className=\"h-9 min-w-0 flex-1 border-0 bg-transparent px-0 shadow-none focus-visible:ring-0 max-sm:flex-none dark:bg-transparent\"\n disabled={starting}\n />\n {recorder?.systemAudioSupported ? (\n <label\n htmlFor={tabAudioId}\n className=\"flex shrink-0 cursor-pointer items-center gap-2 text-sm leading-5 text-fg-label select-none pointer-coarse:min-h-11 max-sm:self-start\"\n title={\n desktopAudio\n ? msg(\"meetings.recorderPanel.recordsTheOtherPeopleIn\")\n : msg(\"meetings.recorderPanel.recordsTheOtherPeopleIn2\")\n }\n >\n <Checkbox\n id={tabAudioId}\n checked={tabAudio}\n disabled={starting}\n onCheckedChange={setTabAudio}\n />\n {desktopAudio\n ? msg(\"meetings.recorderPanel.includeComputerAudio\")\n : msg(\"meetings.recorderPanel.includeATabSAudio\")}\n </label>\n ) : null}\n <RecorderOptions\n language={language}\n onLanguageChange={setLanguage}\n live={\n liveTranscript\n ? {\n on: liveOn,\n usdPerHour: liveTranscript.usdPerHour ?? null,\n onChange: setLiveChoice,\n }\n : null\n }\n disabled={starting}\n />\n <Button\n type=\"submit\"\n disabled={!recorder || starting}\n className=\"shrink-0 rounded-[10px] pointer-coarse:h-11 max-sm:w-full\"\n >\n <CircleIcon aria-hidden=\"true\" className=\"fill-status-failed text-status-failed\" />\n {starting\n ? msg(\"meetings.recorderPanel.starting\")\n : msg(\"meetings.recorderPanel.startRecording\")}\n </Button>\n </form>\n {error ? (\n <Notice\n tone=\"failed\"\n title={recorderErrorText(error, recorder?.systemAudioKind, msg).title}\n onDismiss={() => setErrorDismissed(true)}\n >\n {recorderErrorText(error, recorder?.systemAudioKind, msg).body}\n </Notice>\n ) : null}\n {notice ? <p className=\"px-1 text-sm leading-5 text-fg-label\">{notice}</p> : null}\n <p className=\"px-1 text-xs leading-4.5 text-fg-muted\" aria-live=\"polite\">\n {startHint}\n </p>\n </section>\n );\n}\n\n/**\n * The meeting's language and the live transcript: set once in Meetings\n * settings, so they wait in one small menu beside Start instead of crowding it.\n */\nexport function RecorderOptions({\n language,\n onLanguageChange,\n live,\n disabled,\n defaultOpen = false,\n}: {\n language: string;\n onLanguageChange: (language: string) => void;\n live: { on: boolean; usdPerHour: number | null; onChange: (on: boolean) => void } | null;\n disabled: boolean;\n /** Tests open it without a pointer. */\n defaultOpen?: boolean;\n}) {\n const msg = useOpenGeniText();\n const options = meetingLanguageOptions(\n language,\n msg(\"meetings.recorderPanel.detectLanguage\"),\n msg,\n );\n const current = options.find((option) => option.value === language)?.label ?? language;\n return (\n <DropdownMenu defaultOpen={defaultOpen}>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={disabled}\n aria-label={msg(\"meetings.recorderPanel.recordingOptionsLanguage\", { language: current })}\n className=\"shrink-0 rounded-[10px] text-fg-label pointer-coarse:h-11 max-sm:-ml-3 max-sm:self-start\"\n >\n <LanguagesIcon aria-hidden=\"true\" />\n {current}\n <ChevronDownIcon aria-hidden=\"true\" className=\"text-fg-subtle\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-64\">\n {/* The live transcript first, so it never hides below the languages. */}\n {live ? (\n <>\n <DropdownMenuCheckboxItem\n checked={live.on}\n onCheckedChange={(checked) => live.onChange(checked === true)}\n onSelect={(event) => event.preventDefault()}\n >\n {msg(\"meetings.recorderPanel.liveTranscript\")}\n </DropdownMenuCheckboxItem>\n <DropdownMenuNote>\n {[msg(\"meetings.recorderPanel.showsWhatSSaidAs\"), liveCostHint(live.usdPerHour, msg)]\n .filter(Boolean)\n .join(\" \")}\n </DropdownMenuNote>\n <DropdownMenuSeparator />\n </>\n ) : null}\n <DropdownMenuLabel>{msg(\"meetings.recorderPanel.meetingLanguage\")}</DropdownMenuLabel>\n <DropdownMenuRadioGroup value={language} onValueChange={onLanguageChange}>\n {options.map((option) => (\n <DropdownMenuRadioItem key={option.value} value={option.value}>\n {option.label}\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\n/**\n * What the live preview adds to the bill, where it's switched on; empty when\n * this workspace isn't charged by the hour for it.\n */\nexport function liveCostHint(usdPerHour: number | null, msg: OpenGeniText = defaultText): string {\n return usdPerHour !== null\n ? msg(\"meetings.recorderPanel.theLiveTranscriptAddsAbout\", { value: usdPerHour.toFixed(2) })\n : \"\";\n}\n\nfunction recorderHint(\n {\n desktopAudio,\n starting,\n tabAudio,\n systemAudioSupported,\n }: {\n desktopAudio: boolean;\n starting: boolean;\n tabAudio: boolean;\n systemAudioSupported: boolean;\n },\n msg: OpenGeniText = defaultText,\n): string {\n return desktopAudio\n ? starting\n ? msg(\"meetings.recorderPanel.startingAllowTheMicrophoneAnd\")\n : tabAudio\n ? msg(\"meetings.recorderPanel.recordsYourMicrophoneAndEverything\")\n : msg(\"meetings.recorderPanel.microphoneOnlySoPeopleOn\")\n : starting\n ? tabAudio\n ? msg(\"meetings.recorderPanel.startingAllowTheMicrophoneIf\")\n : msg(\"meetings.recorderPanel.startingAllowTheMicrophoneIf2\")\n : tabAudio\n ? msg(\"meetings.recorderPanel.yourBrowserAsksWhatTo\")\n : systemAudioSupported\n ? msg(\"meetings.recorderPanel.recordsYourMicrophoneForA\")\n : msg(\"meetings.recorderPanel.recordsYourMicrophoneTellEveryone\");\n}\n\nexport function RecorderPanel(props: ComponentProps<typeof RecorderPanelContent>) {\n return (\n <MeetingsOverlayScope>\n <RecorderPanelContent {...props} />\n </MeetingsOverlayScope>\n );\n}\n","/**\n * The live transcript preview: what is being said while a meeting is\n * recorded, one turn per stretch of speech on a track. It is a preview; the\n * meeting's real transcript (with speakers told apart) replaces it once the\n * recording is done.\n */\nimport { useOpenGeniText, createOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\nimport type { RecordingTrack } from \"@opengeni/contracts\";\nimport { useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { ArrowDownIcon } from \"lucide-react\";\n\nimport { Button } from \"../ui/button\";\nimport { cn } from \"../app/lib/utils\";\nimport {\n formatClock,\n groupLiveTurns,\n tidyLiveText,\n tidyPartialText,\n withoutLiveMicrophoneEchoes,\n type LiveTranscriptLine,\n} from \"../recordings\";\n\nimport { SpeakerDot } from \"./meeting-transcript\";\n\nconst defaultText = createOpenGeniText();\n\nexport { groupLiveTurns, tidyLiveText, tidyPartialText, type LiveTranscriptLine };\n\nconst NO_PARTIALS: readonly { trackNumber: number; text: string }[] = [];\nconst NO_TRACKS: readonly { trackNumber: number; source: RecordingTrack[\"source\"] }[] = [];\n\nexport function LiveTranscript({\n lines,\n partials = NO_PARTIALS,\n tracks = NO_TRACKS,\n speakerName,\n status,\n empty,\n heading = true,\n className,\n}: {\n lines: readonly LiveTranscriptLine[];\n /** Words still being heard per track, which may change. */\n partials?: readonly { trackNumber: number; text: string }[];\n /**\n * The recording's tracks. With computer or tab audio beside the\n * microphone, the microphone's echo of the others is left out.\n */\n tracks?: readonly { trackNumber: number; source: RecordingTrack[\"source\"] }[];\n speakerName: (trackNumber: number) => string;\n /** A short line about the connection, such as reconnecting. */\n status?: { text: string; tone: \"muted\" | \"waiting\" } | null;\n /** Shown before anything has been said. */\n empty: string;\n /** Show the \"Live transcript · preview\" heading; off where the page already has one. */\n heading?: boolean;\n className?: string;\n}) {\n const msg = useOpenGeniText();\n const turns = useMemo(\n () => groupLiveTurns(withoutLiveMicrophoneEchoes(lines, tracks)),\n [lines, tracks],\n );\n const heard = partials\n .map((partial) => ({ ...partial, text: tidyPartialText(partial.text) }))\n .filter((partial) => partial.text);\n // Words still being heard from whoever spoke last continue their turn.\n const lastTrack = turns.at(-1)?.trackNumber;\n const continuing = heard.find((partial) => partial.trackNumber === lastTrack) ?? null;\n const newTurns = heard.filter((partial) => partial !== continuing);\n const scrollRef = useRef<HTMLDivElement>(null);\n // Follow the newest words unless the reader scrolled up to reread.\n const following = useRef(true);\n const [scroll, setScroll] = useState({ above: false, behind: false });\n useEffect(() => {\n const element = scrollRef.current;\n if (!element) return;\n const onScroll = () => {\n const atEnd = element.scrollHeight - element.scrollTop - element.clientHeight < 24;\n following.current = atEnd;\n const above = element.scrollTop > 4;\n setScroll((previous) =>\n previous.above === above && previous.behind === !atEnd\n ? previous\n : { above, behind: !atEnd },\n );\n };\n element.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => element.removeEventListener(\"scroll\", onScroll);\n }, []);\n const content = `${turns.length}:${turns.at(-1)?.texts.length ?? 0}:${heard\n .map((partial) => partial.text.length)\n .join(\",\")}`;\n useLayoutEffect(() => {\n const element = scrollRef.current;\n if (!element) return;\n if (following.current) element.scrollTop = element.scrollHeight;\n const above = element.scrollTop > 4;\n setScroll((previous) => (previous.above === above ? previous : { ...previous, above }));\n }, [content]);\n const jumpToLatest = () => {\n const element = scrollRef.current;\n if (!element) return;\n following.current = true;\n element.scrollTop = element.scrollHeight;\n };\n\n const statusLine = status ? (\n status.tone === \"waiting\" ? (\n // A dropped connection is a state of the whole box, so it reads as a banner over it.\n <p\n className=\"flex items-start gap-2 rounded-[10px] border border-status-waiting/40 bg-status-waiting/10 px-3 py-2 text-xs leading-4.5 font-medium text-fg-label\"\n aria-live=\"polite\"\n >\n <span\n aria-hidden=\"true\"\n className=\"mt-1.5 inline-block size-1.5 shrink-0 animate-pulse rounded-full bg-status-waiting motion-reduce:animate-none\"\n />\n {status.text}\n </p>\n ) : (\n <p className=\"text-xs leading-4 text-fg-muted\" aria-live=\"polite\">\n {status.text}\n </p>\n )\n ) : null;\n\n return (\n <section\n aria-label={msg(\"meetings.liveTranscript.liveTranscript\")}\n className={cn(\"grid min-w-0 gap-2\", className)}\n >\n {heading ? (\n <>\n <div className=\"flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1\">\n <h3 className=\"text-xs leading-4 font-medium text-fg-label\">\n {msg(\"meetings.liveTranscript.liveTranscript\")}{\" \"}\n <span className=\"font-normal text-fg-muted\">\n {msg(\"meetings.liveTranscript.preview\")}\n </span>\n </h3>\n {status?.tone === \"muted\" ? statusLine : null}\n </div>\n {status?.tone === \"waiting\" ? statusLine : null}\n </>\n ) : (\n statusLine\n )}\n <div className=\"relative min-w-0 rounded-[10px] border border-border bg-surface-2/60\">\n <div\n ref={scrollRef}\n role=\"log\"\n aria-live=\"polite\"\n aria-label={msg(\"meetings.liveTranscript.liveTranscriptText\")}\n tabIndex={0}\n className={cn(\n \"max-h-64 min-h-16 overflow-y-auto rounded-[10px] px-3 py-2.5 focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-hidden\",\n // Older text above fades out, so a clipped first line reads as \"scroll up\".\n scroll.above && \"[mask-image:linear-gradient(to_bottom,transparent,black_2.5rem)]\",\n )}\n >\n {turns.length === 0 && heard.length === 0 ? (\n <p className=\"text-sm leading-5 text-fg-muted\">{empty}</p>\n ) : (\n <ol className=\"grid gap-3\">\n {turns.map((turn, index) => (\n <li key={turn.key} className=\"grid min-w-0 gap-0.5\">\n <div className=\"flex items-center gap-2\">\n <SpeakerDot slot={turn.trackNumber + 1} />\n <span className=\"text-xs leading-4 font-semibold text-fg\">\n {speakerName(turn.trackNumber)}\n </span>\n <span className=\"text-xs leading-4 text-fg-muted tabular-nums\">\n {formatClock(turn.startMilliseconds)}\n </span>\n </div>\n <p className=\"text-sm leading-5 text-pretty text-fg\">\n {tidyLiveText(turn.texts)}\n {continuing && index === turns.length - 1 ? (\n <span className=\"text-fg-label\"> {continuing.text}</span>\n ) : null}\n </p>\n </li>\n ))}\n {newTurns.map((partial) => (\n <li key={`partial:${partial.trackNumber}`} className=\"grid min-w-0 gap-0.5\">\n <div className=\"flex items-center gap-2\">\n <SpeakerDot slot={partial.trackNumber + 1} />\n <span className=\"text-xs leading-4 font-semibold text-fg\">\n {speakerName(partial.trackNumber)}\n </span>\n <span className=\"inline-flex items-center gap-1 text-xs leading-4 font-medium text-fg-label\">\n <span\n aria-hidden=\"true\"\n className=\"inline-block size-1.5 animate-pulse rounded-full bg-status-waiting motion-reduce:animate-none\"\n />\n {msg(\"meetings.liveTranscript.now\")}\n </span>\n </div>\n <p className=\"text-sm leading-5 text-fg-label\">{partial.text}</p>\n </li>\n ))}\n </ol>\n )}\n </div>\n {scroll.behind ? (\n <Button\n type=\"button\"\n size=\"xs\"\n variant=\"outline\"\n onClick={jumpToLatest}\n className=\"absolute right-3 bottom-2 rounded-full bg-surface shadow-[0_1px_2px_rgb(0_0_0/0.08)] pointer-coarse:h-11\"\n >\n <ArrowDownIcon aria-hidden=\"true\" />\n {msg(\"meetings.liveTranscript.latest\")}\n </Button>\n ) : null}\n </div>\n </section>\n );\n}\n\n/** The local recorder's live state as the panel's status line, or null when all is well. */\nexport function liveStatus(\n tracks: readonly { state: string; error: { message: string } | null }[],\n msg: OpenGeniText = defaultText,\n): { text: string; tone: \"muted\" | \"waiting\" } | null {\n if (tracks.length === 0) return null;\n if (tracks.every((track) => track.state === \"unavailable\")) {\n return {\n text: msg(\"meetings.liveTranscript.livePreviewUnavailableTheRecording\"),\n tone: \"muted\",\n };\n }\n if (tracks.some((track) => track.state === \"reconnecting\")) {\n return {\n text: msg(\"meetings.liveTranscript.reconnectingTheLiveTextThe\"),\n tone: \"waiting\",\n };\n }\n if (tracks.every((track) => track.state === \"connecting\")) {\n return { text: msg(\"meetings.liveTranscript.connecting\"), tone: \"muted\" };\n }\n return null;\n}\n","/**\n * The transcript as a person reads it: turns of one speaker, each a soft\n * bubble under the speaker's name in their colour, with its time and the line\n * playing now highlighted. A speaker's name opens \"Who is this?\" (someone from\n * the people directory, or a new name); a turn's pencil corrects its words and\n * its ⋯ menu moves it to another speaker. A name recognized by voice is marked\n * suggested until someone confirms or turns it down.\n */\nimport { useOpenGeniText, createOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\nimport {\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ComponentProps,\n type CSSProperties,\n} from \"react\";\nimport {\n AudioLinesIcon,\n CheckIcon,\n ChevronDownIcon,\n MoreHorizontalIcon,\n PencilIcon,\n UserIcon,\n UserPlusIcon,\n UsersIcon,\n XIcon,\n} from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\nimport type {\n RecordingPerson,\n RecordingSpeaker,\n RecordingTrack,\n RecordingTranscriptSegment,\n} from \"@opengeni/contracts\";\n\nimport { Button } from \"../ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"../ui/dropdown-menu\";\nimport { Field, FieldStack, TextArea, TextInput } from \"../ui/field\";\nimport { FormDialog } from \"../ui/form-dialog\";\nimport { cn } from \"../app/lib/utils\";\n\nimport {\n formatClock,\n groupTranscriptTurns,\n speakerColorSlots,\n speakerDisplayName,\n speakerIsNamed,\n type TranscriptTurn,\n} from \"../recordings\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\n\nconst defaultText = createOpenGeniText();\n\n/** The chart palette, one hue per voice. */\nconst SPEAKER_DOT: Record<number, string> = {\n 1: \"bg-chart-1\",\n 2: \"bg-chart-2\",\n 3: \"bg-chart-3\",\n 4: \"bg-chart-4\",\n 5: \"bg-chart-5\",\n 6: \"bg-chart-6\",\n};\n\n/**\n * A voice's hue, for its name and mentions; the shared rules below mix it.\n * Set inline, so the six slots cost no stylesheet rules.\n */\nexport function speakerHueStyle(slot: number | undefined): CSSProperties | undefined {\n return slot !== undefined && SPEAKER_DOT[slot]\n ? ({ \"--speaker-hue\": `var(--color-chart-${slot})` } as CSSProperties)\n : undefined;\n}\n\n/**\n * The hue mixed toward the text colour, so it reads on both themes: darker on\n * light, lighter on dark. Light takes more of the text colour (about 5:1 or\n * better on the page and on a mention's tint); dark keeps more hue at the\n * same contrast.\n */\nconst SPEAKER_TEXT =\n \"text-[color-mix(in_oklab,var(--speaker-hue)_50%,var(--color-fg))] dark:text-[color-mix(in_oklab,var(--speaker-hue)_62%,var(--color-fg))]\";\n\n/** A faint fill in the voice's hue, for a mention of that speaker. */\nconst SPEAKER_TINT = \"bg-[color-mix(in_oklab,var(--speaker-hue)_14%,transparent)]\";\n\n/** The text colour of a speaker's colour slot, with {@link speakerHueStyle}; muted when there is none. */\nexport function speakerTextClass(slot: number | undefined): string {\n return speakerHueStyle(slot) ? SPEAKER_TEXT : \"text-fg-muted\";\n}\n\n/** The faint fill of a speaker's colour slot, with {@link speakerHueStyle}; the chip surface when there is none. */\nexport function speakerTintClass(slot: number | undefined): string {\n return speakerHueStyle(slot) ? SPEAKER_TINT : \"bg-surface-2\";\n}\n\n/** A turn's pencil and ⋯: shown on hover or focus of the turn, always on touch. */\nconst TURN_ACTION =\n \"size-7 rounded-[8px] text-fg-subtle opacity-0 transition-opacity duration-[120ms] group-hover/turn:opacity-100 group-focus-within/turn:opacity-100 focus-visible:opacity-100 data-[state=open]:opacity-100 motion-reduce:transition-none pointer-coarse:size-11 pointer-coarse:opacity-100\";\n\nexport function SpeakerDot({ slot, className }: { slot: number | undefined; className?: string }) {\n return (\n <span\n aria-hidden=\"true\"\n className={cn(\n \"size-2 shrink-0 rounded-full\",\n SPEAKER_DOT[slot ?? 0] ?? \"bg-fg-subtle\",\n className,\n )}\n />\n );\n}\n\nexport type TranscriptActions = {\n nameSpeaker: (\n label: string,\n name: { personId: string } | { name: string } | null,\n ) => Promise<void>;\n /** Turn down a name suggested from a voice. */\n rejectSuggestion: (label: string) => Promise<void>;\n createPerson: (displayName: string) => Promise<RecordingPerson>;\n /**\n * Name a speaker as the person reading, linked to their account so their\n * own voice can be remembered. Null when there is no signed-in member.\n */\n nameSelf: ((label: string) => Promise<void>) | null;\n /** Who is reading, to tell their own entry in the people list apart. */\n viewerSubjectId: string | null;\n moveSegment: (segmentIndex: number, label: string) => Promise<void>;\n editSegment: (segmentIndex: number, text: string | null) => Promise<void>;\n /** Null when the workspace doesn't recognize people by voice. */\n voices: VoiceActions | null;\n};\n\n/** Remembering and forgetting voices, from a named speaker's menu. */\nexport type VoiceActions = {\n viewerSubjectId: string;\n /** Asks first when the person is someone from outside the workspace. */\n remember: (person: RecordingPerson) => void;\n forget: (person: RecordingPerson) => Promise<void>;\n};\n\n/** The speaker's name came from their voice and nobody has confirmed it yet. */\nexport function speakerIsSuggested(\n label: string | null,\n speakers: readonly RecordingSpeaker[],\n): RecordingSpeaker | null {\n if (!label) return null;\n const speaker = speakers.find((candidate) => candidate.label === label);\n return speaker?.source === \"suggested\" && speaker.personId ? speaker : null;\n}\n\n/** \"92% match\", from the voice similarity behind a suggestion. */\nexport function suggestionMatch(\n speaker: RecordingSpeaker,\n msg: OpenGeniText = defaultText,\n): string | null {\n return speaker.confidence === null\n ? null\n : msg(\"meetings.transcript.valueMatch\", {\n value: Math.round(Math.max(0, Math.min(1, speaker.confidence)) * 100),\n });\n}\n\nasync function withToast(failure: string, work: () => Promise<void>): Promise<boolean> {\n try {\n await work();\n return true;\n } catch (error) {\n toast.error(failure, {\n description: error instanceof Error ? userErrorText(error) : undefined,\n });\n return false;\n }\n}\n\n/**\n * \"Who is Speaker 2?\": pick a person, add a new name, or clear it. People\n * already named in this meeting come first as \"Same person as …\", because\n * picking one joins the two voices under one name.\n */\nexport function SpeakerNameMenu({\n label,\n displayName,\n speakers,\n people,\n actions,\n onAddNew,\n children,\n align = \"start\",\n defaultOpen,\n}: {\n label: string;\n displayName: string;\n speakers: readonly RecordingSpeaker[];\n people: readonly RecordingPerson[];\n actions: TranscriptActions;\n onAddNew: (label: string) => void;\n children: React.ReactNode;\n align?: \"start\" | \"end\";\n /** Open on first render, for previews. */\n defaultOpen?: boolean;\n}) {\n const msg = useOpenGeniText();\n const current = speakers.find((speaker) => speaker.label === label);\n const named = speakerIsNamed(label, speakers);\n const suggested = speakerIsSuggested(label, speakers);\n const inMeeting = useMemo(() => {\n const ids = new Set(\n speakers\n .filter((speaker) => speaker.label !== label && speaker.personId)\n .map((speaker) => speaker.personId!),\n );\n return people.filter((person) => ids.has(person.id) && person.id !== current?.personId);\n }, [people, speakers, label, current?.personId]);\n const viewerSubjectId = actions.viewerSubjectId;\n const others = useMemo(\n () =>\n people\n // A suggested person is already the first choice above, and the\n // reader is \"It's me\".\n .filter(\n (person) =>\n !inMeeting.includes(person) &&\n !(current?.source === \"suggested\" && person.id === current.personId) &&\n !(viewerSubjectId && person.memberSubjectId === viewerSubjectId),\n )\n .sort((a, b) => a.displayName.localeCompare(b.displayName))\n .slice(0, 12),\n [people, inMeeting, current?.source, current?.personId, viewerSubjectId],\n );\n const pick = (person: RecordingPerson) =>\n void withToast(msg(\"meetings.transcript.couldnTNameThisSpeaker\"), () =>\n actions.nameSpeaker(label, { personId: person.id }),\n );\n const nameSelf = actions.nameSelf;\n const isSelf = Boolean(\n viewerSubjectId &&\n current?.personId &&\n people.some(\n (person) => person.id === current.personId && person.memberSubjectId === viewerSubjectId,\n ),\n );\n const selfItem =\n nameSelf && !isSelf ? (\n <DropdownMenuItem\n onSelect={() =>\n void withToast(msg(\"meetings.transcript.couldnTNameThisSpeaker\"), () => nameSelf(label))\n }\n >\n <UserIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.itSMe\")}\n </DropdownMenuItem>\n ) : null;\n const currentPerson = current?.personId\n ? (people.find((candidate) => candidate.id === current.personId) ?? null)\n : null;\n const voiceItem =\n !suggested && currentPerson && actions.voices\n ? voiceMenuItem(currentPerson, actions.voices, msg)\n : null;\n return (\n <DropdownMenu {...(defaultOpen ? { defaultOpen } : {})}>\n <DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger>\n <DropdownMenuContent align={align} className=\"max-h-80 min-w-56\">\n {suggested ? (\n <>\n <DropdownMenuLabel className=\"grid gap-0.5\">\n <span>\n {msg(\"meetings.transcript.isThisDisplayname\", { displayName: displayName })}\n </span>\n <span className=\"text-xs leading-4 font-normal text-fg-muted\">\n {suggestionMatch(suggested, msg)\n ? msg(\"meetings.transcript.suggestedBecauseTheVoiceSounds\", {\n suggestionMatch: suggestionMatch(suggested, msg),\n })\n : msg(\"meetings.transcript.suggestedBecauseTheVoiceSounds2\")}\n </span>\n </DropdownMenuLabel>\n <DropdownMenuItem\n onSelect={() =>\n void withToast(msg(\"meetings.transcript.couldnTConfirmThisName\"), () =>\n actions.nameSpeaker(label, { personId: suggested.personId! }),\n )\n }\n >\n <CheckIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.yesItSDisplayname\", { displayName: displayName })}\n </DropdownMenuItem>\n <DropdownMenuItem\n onSelect={() =>\n void withToast(msg(\"meetings.transcript.couldnTTurnDownThis\"), () =>\n actions.rejectSuggestion(label),\n )\n }\n >\n <XIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.noLeaveUnnamed\")}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuLabel className=\"text-xs leading-4 font-normal text-fg-muted\">\n {msg(\"meetings.transcript.orPickWhoItIs\")}\n </DropdownMenuLabel>\n </>\n ) : (\n <DropdownMenuLabel>\n {msg(\"meetings.transcript.whoIsDisplayname\", { displayName: displayName })}\n </DropdownMenuLabel>\n )}\n {selfItem}\n {selfItem && inMeeting.length + others.length > 0 ? <DropdownMenuSeparator /> : null}\n {inMeeting.map((person) => (\n <DropdownMenuItem key={person.id} onSelect={() => pick(person)}>\n <span className=\"min-w-0 flex-1 truncate\">\n {msg(\"meetings.transcript.samePersonAsDisplayname\", {\n displayName: person.displayName,\n })}\n </span>\n </DropdownMenuItem>\n ))}\n {inMeeting.length > 0 && others.length > 0 ? <DropdownMenuSeparator /> : null}\n {others.map((person) => (\n <DropdownMenuItem key={person.id} onSelect={() => pick(person)}>\n <span className=\"min-w-0 flex-1 truncate\">{person.displayName}</span>\n {current?.personId === person.id && !suggested ? (\n <CheckIcon aria-hidden=\"true\" className=\"text-brand\" />\n ) : null}\n </DropdownMenuItem>\n ))}\n {inMeeting.length + others.length > 0 ? <DropdownMenuSeparator /> : null}\n <DropdownMenuItem onSelect={() => onAddNew(label)}>\n <UserPlusIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.someoneNew\")}\n </DropdownMenuItem>\n {named && !suggested ? (\n <DropdownMenuItem\n onSelect={() =>\n void withToast(msg(\"meetings.transcript.couldnTClearThisName\"), () =>\n actions.nameSpeaker(label, null),\n )\n }\n >\n <XIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.removeName\")}\n </DropdownMenuItem>\n ) : null}\n {voiceItem ? (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuLabel className=\"text-xs leading-4 font-normal text-fg-muted\">\n {msg(\"meetings.transcript.usedToSuggestNamesIn\")}\n </DropdownMenuLabel>\n {voiceItem}\n </>\n ) : null}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\n/**\n * \"Remember my voice\", \"Remember Maja's voice…\" or \"Forget …\": members only\n * decide for themselves, so another member's voice offers nothing here.\n */\nfunction voiceMenuItem(\n person: RecordingPerson,\n voices: VoiceActions,\n msg: OpenGeniText = defaultText,\n): React.ReactNode {\n const self = person.memberSubjectId === voices.viewerSubjectId;\n if (person.memberSubjectId && !self) return null;\n if (person.voice) {\n return (\n <DropdownMenuItem\n onSelect={() =>\n void withToast(msg(\"meetings.transcript.couldnTForgetThisVoice\"), () =>\n voices.forget(person),\n )\n }\n >\n <AudioLinesIcon aria-hidden=\"true\" />\n <span className=\"min-w-0 flex-1 truncate\">\n {self\n ? msg(\"meetings.transcript.forgetMyVoice\")\n : msg(\"meetings.transcript.forgetDisplaynameSVoice\", {\n displayName: person.displayName,\n })}\n </span>\n </DropdownMenuItem>\n );\n }\n return (\n <DropdownMenuItem onSelect={() => voices.remember(person)}>\n <AudioLinesIcon aria-hidden=\"true\" />\n <span className=\"min-w-0 flex-1 truncate\">\n {self\n ? msg(\"meetings.transcript.rememberMyVoice\")\n : msg(\"meetings.transcript.rememberDisplaynameSVoice\", {\n displayName: person.displayName,\n })}\n </span>\n </DropdownMenuItem>\n );\n}\n\n/** \"Name this speaker\": adds them to the people directory and names the voice. */\nexport function NewSpeakerNameDialog({\n label,\n displayName,\n actions,\n onClose,\n}: {\n label: string | null;\n displayName: string;\n actions: TranscriptActions;\n onClose: () => void;\n}) {\n const msg = useOpenGeniText();\n const [name, setName] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n return (\n <FormDialog\n open={label !== null}\n onOpenChange={(open) => {\n if (!open) {\n onClose();\n setName(\"\");\n setError(null);\n }\n }}\n title={msg(\"meetings.transcript.whoIsDisplayname\", { displayName: displayName })}\n description={msg(\"meetings.transcript.theNameIsAddedTo\")}\n submitLabel={msg(\"meetings.transcript.saveName\")}\n pendingLabel={msg(\"meetings.transcript.saving\")}\n submitDisabled={!name.trim()}\n error={error}\n onSubmit={async () => {\n if (!label || !name.trim()) return false;\n try {\n const person = await actions.createPerson(name.trim());\n await actions.nameSpeaker(label, { personId: person.id });\n } catch (cause) {\n setError(\n cause instanceof Error ? cause.message : msg(\"meetings.transcript.couldnTSaveThisName\"),\n );\n return false;\n }\n setName(\"\");\n setError(null);\n }}\n onSubmitted={onClose}\n >\n <FieldStack>\n <Field label={msg(\"meetings.transcript.name\")}>\n <TextInput\n value={name}\n maxLength={200}\n autoComplete=\"off\"\n onChange={(event) => setName(event.target.value)}\n placeholder={msg(\"meetings.transcript.forExampleMajaBerg\")}\n />\n </Field>\n </FieldStack>\n </FormDialog>\n );\n}\n\nfunction EditTurnDialog({\n turn,\n speakerName,\n onClose,\n actions,\n}: {\n turn: TranscriptTurn | null;\n speakerName: string;\n onClose: () => void;\n actions: TranscriptActions;\n}) {\n const msg = useOpenGeniText();\n const [drafts, setDrafts] = useState<Record<number, string>>({});\n const formId = useId();\n const changed =\n turn?.segments.some(\n (segment) => drafts[segment.index] !== undefined && drafts[segment.index] !== segment.text,\n ) ?? false;\n return (\n <FormDialog\n open={turn !== null}\n onOpenChange={(open) => {\n if (!open) {\n onClose();\n setDrafts({});\n }\n }}\n size=\"lg\"\n title={msg(\"meetings.transcript.correctTheWords\")}\n description={msg(\"meetings.transcript.fixWhatTheTranscriptGot\")}\n submitLabel={msg(\"meetings.transcript.save\")}\n pendingLabel={msg(\"meetings.transcript.saving\")}\n submitDisabled={!changed}\n onSubmit={async () => {\n if (!turn) return;\n const changes = turn.segments.filter(\n (segment) =>\n drafts[segment.index] !== undefined && drafts[segment.index] !== segment.text,\n );\n const ok = await withToast(\n msg(\"meetings.transcript.couldnTSaveTheCorrection\"),\n async () => {\n for (const segment of changes) {\n const text = drafts[segment.index]!.trim();\n await actions.editSegment(segment.index, text.length > 0 ? text : null);\n }\n },\n );\n if (!ok) return false;\n setDrafts({});\n }}\n onSubmitted={onClose}\n >\n <FieldStack>\n {turn?.segments.map((segment) => (\n <Field\n key={segment.index}\n label={msg(\"meetings.transcript.speakernameAtFormatclock\", {\n speakerName: speakerName,\n formatClock: formatClock(segment.startMilliseconds),\n })}\n >\n <TextArea\n id={`${formId}-${segment.index}`}\n rows={Math.min(8, Math.max(2, Math.ceil(segment.text.length / 80)))}\n value={drafts[segment.index] ?? segment.text}\n onChange={(event) =>\n setDrafts((current) => ({ ...current, [segment.index]: event.target.value }))\n }\n />\n </Field>\n ))}\n </FieldStack>\n </FormDialog>\n );\n}\n\nfunction MeetingTranscriptContent({\n segments,\n speakers,\n tracks,\n people,\n activeSegment,\n actions,\n onSeek,\n}: {\n segments: readonly RecordingTranscriptSegment[];\n speakers: readonly RecordingSpeaker[];\n tracks: readonly RecordingTrack[];\n people: readonly RecordingPerson[];\n /** The segment playing now. */\n activeSegment: number | null;\n actions: TranscriptActions;\n /** Null when there is no audio to play. */\n onSeek: ((milliseconds: number) => void) | null;\n}) {\n const msg = useOpenGeniText();\n const turns = useMemo(() => groupTranscriptTurns(segments), [segments]);\n const slots = useMemo(() => speakerColorSlots(segments), [segments]);\n const labels = useMemo(() => [...slots.keys()], [slots]);\n const [naming, setNaming] = useState<string | null>(null);\n const [editing, setEditing] = useState<TranscriptTurn | null>(null);\n const nameOf = (label: string | null) => speakerDisplayName(label, speakers, tracks, msg);\n const listRef = useRef<HTMLOListElement>(null);\n // Follow playback: keep the playing line in view while the reader is\n // following it, and stop following once they scroll elsewhere.\n const previousActive = useRef<number | null>(null);\n useEffect(() => {\n const list = listRef.current;\n if (!list || activeSegment === null) {\n previousActive.current = activeSegment;\n return;\n }\n const visible = (element: Element | null) => {\n if (!element) return false;\n const box = element.getBoundingClientRect();\n return box.bottom > 0 && box.top < window.innerHeight;\n };\n const previous =\n previousActive.current === null\n ? null\n : list.querySelector(`[data-segment=\"${previousActive.current}\"]`);\n const next = list.querySelector(`[data-segment=\"${activeSegment}\"]`);\n previousActive.current = activeSegment;\n if (!next || visible(next) || (previous && !visible(previous))) return;\n const reduce = window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches;\n next.scrollIntoView({ block: \"center\", behavior: reduce ? \"auto\" : \"smooth\" });\n }, [activeSegment]);\n\n return (\n <>\n <ol ref={listRef} className=\"grid gap-6\" aria-label={msg(\"meetings.transcript.transcript\")}>\n {turns.map((turn) => {\n const name = nameOf(turn.speakerLabel);\n const unnamed = turn.speakerLabel ? !speakerIsNamed(turn.speakerLabel, speakers) : false;\n const suggested = speakerIsSuggested(turn.speakerLabel, speakers);\n const slot = turn.speakerLabel ? slots.get(turn.speakerLabel) : undefined;\n const at = formatClock(turn.startMilliseconds);\n return (\n <li\n key={turn.key}\n data-turn={turn.key}\n className=\"group/turn grid max-w-[72ch] min-w-0 gap-1.5\"\n >\n <div className=\"flex min-w-0 items-center gap-2 pl-1\">\n {turn.speakerLabel ? (\n <SpeakerNameMenu\n label={turn.speakerLabel}\n displayName={name}\n speakers={speakers}\n people={people}\n actions={actions}\n onAddNew={setNaming}\n >\n <button\n type=\"button\"\n aria-label={\n unnamed\n ? msg(\"meetings.transcript.nameNameThisSpeaker\", { name: name })\n : suggested\n ? msg(\"meetings.transcript.nameSuggestedFromTheirVoice\", { name: name })\n : msg(\"meetings.transcript.nameChangeWhoThisIs\", { name: name })\n }\n className=\"group/speaker -mx-1.5 flex min-w-0 items-center gap-2 rounded-[6px] px-1.5 py-0.5 text-sm leading-5 font-semibold transition-colors duration-[120ms] hover:bg-hover data-[state=open]:bg-hover pointer-coarse:min-h-11\"\n >\n <span\n data-speaker-name=\"\"\n className={cn(\"truncate\", speakerTextClass(slot))}\n style={speakerHueStyle(slot)}\n >\n {name}\n </span>\n {suggested ? (\n <span className=\"shrink-0 rounded-full border border-dashed border-border-strong px-1.5 text-xs leading-4 font-normal text-fg-muted\">\n {msg(\"meetings.transcript.suggested\")}\n </span>\n ) : null}\n {unnamed ? (\n // An unnamed speaker always shows it can be named, not only on hover.\n <span className=\"flex shrink-0 items-center gap-1 text-xs leading-4 font-normal text-fg-muted group-hover/speaker:text-fg\">\n <PencilIcon aria-hidden=\"true\" className=\"size-3\" />\n {msg(\"meetings.transcript.name\")}\n </span>\n ) : (\n <ChevronDownIcon\n aria-hidden=\"true\"\n className=\"size-3.5 shrink-0 text-fg-subtle opacity-0 transition-opacity duration-[120ms] group-hover/speaker:opacity-100 group-focus-visible/speaker:opacity-100 group-data-[state=open]/speaker:opacity-100 pointer-coarse:opacity-100 motion-reduce:transition-none\"\n />\n )}\n </button>\n </SpeakerNameMenu>\n ) : (\n <span className=\"text-sm leading-5 font-semibold text-fg-muted\">{name}</span>\n )}\n {onSeek ? (\n <button\n type=\"button\"\n onClick={() => onSeek(turn.startMilliseconds)}\n className=\"rounded-[6px] px-1 text-xs leading-4 text-fg-muted tabular-nums underline-offset-2 transition-colors duration-[120ms] hover:text-fg hover:underline pointer-coarse:min-h-11\"\n aria-label={msg(\"meetings.transcript.playFromFormatclock\", {\n formatClock: at,\n })}\n >\n {at}\n </button>\n ) : (\n <span className=\"text-xs leading-4 text-fg-muted tabular-nums\">{at}</span>\n )}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={msg(\"meetings.transcript.correctTheWordsOfNameAt\", {\n name: name,\n formatClock: at,\n })}\n onClick={() => setEditing(turn)}\n className={cn(\"ml-auto\", TURN_ACTION)}\n >\n <PencilIcon />\n </Button>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={msg(\"meetings.transcript.moreActionsForNameAt\", {\n name: name,\n formatClock: at,\n })}\n className={TURN_ACTION}\n >\n <MoreHorizontalIcon />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"min-w-52\">\n {labels.length > 1 ? (\n <DropdownMenuSub>\n <DropdownMenuSubTrigger>\n <UsersIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.changeSpeaker\")}\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent className=\"min-w-48\">\n {labels\n .filter((label) => label !== turn.speakerLabel)\n .map((label) => (\n <DropdownMenuItem\n key={label}\n onSelect={() =>\n void withToast(\n msg(\"meetings.transcript.couldnTChangeTheSpeaker\"),\n async () => {\n for (const segment of turn.segments) {\n await actions.moveSegment(segment.index, label);\n }\n },\n )\n }\n >\n <SpeakerDot slot={slots.get(label)} />\n <span className=\"min-w-0 flex-1 truncate\">{nameOf(label)}</span>\n </DropdownMenuItem>\n ))}\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n ) : null}\n <DropdownMenuItem onSelect={() => setEditing(turn)}>\n <PencilIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.correctTheWords\")}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n {/* A soft bubble, left-aligned for everyone, like a chat. */}\n <p\n data-turn-bubble=\"\"\n className=\"w-fit max-w-full rounded-[14px] rounded-tl-[4px] bg-surface-2 px-3.5 py-2 text-[15px] leading-6 text-pretty text-fg\"\n >\n {turn.segments.map((segment, position) => (\n <span key={segment.index}>\n {position > 0 ? \" \" : null}\n <span\n data-segment={segment.index}\n className={cn(\n \"rounded-[3px] transition-colors duration-[120ms] box-decoration-clone\",\n segment.index === activeSegment && \"bg-brand/15 text-fg\",\n onSeek && \"cursor-pointer hover:bg-hover\",\n )}\n onClick={onSeek ? () => onSeek(segment.startMilliseconds) : undefined}\n >\n {segment.text}\n </span>\n {segment.edited ? (\n <span className=\"sr-only\">{msg(\"meetings.transcript.corrected\")}</span>\n ) : null}\n </span>\n ))}\n </p>\n </li>\n );\n })}\n </ol>\n <NewSpeakerNameDialog\n label={naming}\n displayName={naming ? nameOf(naming) : \"\"}\n actions={actions}\n onClose={() => setNaming(null)}\n />\n <EditTurnDialog\n turn={editing}\n speakerName={editing ? nameOf(editing.speakerLabel) : \"\"}\n onClose={() => setEditing(null)}\n actions={actions}\n />\n </>\n );\n}\n\nexport function MeetingTranscript(props: ComponentProps<typeof MeetingTranscriptContent>) {\n return (\n <MeetingsOverlayScope>\n <MeetingTranscriptContent {...props} />\n </MeetingsOverlayScope>\n );\n}\n","import { createContext, useCallback, useContext, useRef, useState, type ReactNode } from \"react\";\n\nimport { useHostTheme } from \"../lib/host-theme\";\nimport { StandaloneOverlayRoot } from \"../ui/portal-container\";\n\nconst InsideScope = createContext(false);\n\n/**\n * The root of a meetings component, as the embedded chat's root is: it takes\n * light or dark and its surfaces from the page it sits on, so its page\n * background, sticky bars and cards match a host page instead of Opengeni's\n * own greys (inside Opengeni's app, or under an embed root that already did\n * this, nothing changes). Its menus and dialogs stay inside Opengeni's scoped\n * stylesheet and theme: they open in an `og-root` layer under <body> that\n * carries the component's tokens; inside an app that already provides a\n * portal container, that container is used. A component inside another one\n * (the transcript on a meeting's page) uses the outer scope.\n */\nexport function MeetingsOverlayScope({ children }: { children: ReactNode }) {\n const inside = useContext(InsideScope);\n if (inside) return <>{children}</>;\n return <MeetingsRoot>{children}</MeetingsRoot>;\n}\n\nfunction MeetingsRoot({ children }: { children: ReactNode }) {\n const root = useRef<HTMLDivElement | null>(null);\n const [source, setSource] = useState<HTMLDivElement | null>(null);\n const hostTheme = useHostTheme(root, {});\n const ref = useCallback((node: HTMLDivElement | null) => {\n root.current = node;\n setSource(node);\n }, []);\n return (\n // `og-root` re-derives the stylesheet's colors from the tokens set here.\n <div\n ref={ref}\n className=\"og-root\"\n style={{ ...hostTheme.style, display: \"contents\" }}\n data-og-theme={hostTheme.attribute}\n data-og-host-theme=\"\"\n >\n <InsideScope.Provider value>\n <StandaloneOverlayRoot source={source}>{children}</StandaloneOverlayRoot>\n </InsideScope.Provider>\n </div>\n );\n}\n","/**\n * Meetings: the recorder on top, then every meeting this person can see,\n * newest first. A row opens the meeting's own page. Rows still recording, in\n * progress elsewhere or transcribing say so and update on their own.\n */\nimport { useOpenGeniText } from \"../messages/runtime\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n type ComponentProps,\n} from \"react\";\nimport { AudioLinesIcon, LockIcon, SearchIcon, Trash2Icon } from \"lucide-react\";\nimport type { Recording } from \"@opengeni/contracts\";\nimport {\n formatDuration,\n meetingHereStatus,\n meetingPhase,\n meetingStatusLabel,\n meetingTitle,\n useRecordingModels,\n useRecordings,\n useRecordingsClient,\n type RecordingsClientOverride,\n} from \"../recordings\";\n\nimport { Button } from \"../ui/button\";\nimport { DropdownMenuItem } from \"../ui/dropdown-menu\";\nimport { EmptyState } from \"../ui/empty-state\";\nimport { ErrorMessage } from \"../ui/error-message\";\nimport { inAppClick } from \"../ui/in-app-click\";\nimport { Input } from \"../ui/input\";\nimport { ListRow, ListRowSkeleton, RowList, type RowListColumn } from \"../ui/list-row\";\nimport { LogoTile } from \"../ui/logo-tile\";\nimport { MetaChip } from \"../ui/meta-chip\";\nimport { Notice } from \"../ui/notice\";\nimport { PageHeader } from \"../ui/page-header\";\nimport { RelativeTime } from \"../ui/relative-time\";\nimport { StatusBadge } from \"../ui/status-badge\";\n\nimport { DeleteMeetingDialog } from \"./delete-meeting-dialog\";\nimport { RecorderPanel, useOnline } from \"./recorder-panel\";\nimport { useMeetingRecorder, usePendingMeetingStart } from \"./recorder-context\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\n\nfunction useDebounced<T>(value: T, delay: number): T {\n const [debounced, setDebounced] = useState(value);\n useEffect(() => {\n const timer = window.setTimeout(() => setDebounced(value), delay);\n return () => window.clearTimeout(timer);\n }, [value, delay]);\n return debounced;\n}\n\nfunction useNarrow(): boolean {\n const query = \"(max-width: 639px)\";\n const [narrow, setNarrow] = useState(\n () => typeof window !== \"undefined\" && window.matchMedia?.(query).matches === true,\n );\n useEffect(() => {\n const media = window.matchMedia?.(query);\n if (!media) return;\n const update = () => setNarrow(media.matches);\n update();\n media.addEventListener(\"change\", update);\n return () => media.removeEventListener(\"change\", update);\n }, []);\n return narrow;\n}\n\nfunction MeetingsListPageContent({\n workspaceId,\n liveTranscriptDefault,\n liveTranscript = true,\n defaultLanguage,\n recordings: recordingsClient,\n meetingHref,\n onOpen,\n externalRef = null,\n notice = null,\n header = true,\n recordingOff = null,\n viewerName = null,\n}: {\n workspaceId: string;\n /**\n * Whether the recorder starts with the live transcript on. By default the\n * workspace's setting, from the server.\n */\n liveTranscriptDefault?: boolean;\n /** Offer the live transcript preview at all; false hides it even when a live model is connected. */\n liveTranscript?: boolean;\n /**\n * The language the recorder starts on; null detects it. By default the\n * workspace's meeting language, from the server.\n */\n defaultLanguage?: string | null;\n /** A recordings client to use instead of the app's, for previews. */\n recordings?: RecordingsClientOverride[\"recordings\"];\n meetingHref: (recordingId: string) => string;\n onOpen: (recordingId: string) => void;\n /**\n * Show only the meetings with this id of the host's, such as a project, and\n * give new recordings started here the same id.\n */\n externalRef?: string | null;\n /** A short line shown before every start, such as a reminder to tell the people present. */\n notice?: ReactNode;\n /** Show the page title; false when the list sits inside a page of the host's. */\n header?: boolean;\n /**\n * Shown instead of the recorder when the host doesn't let this person record\n * here, such as a setting an administrator has to turn on first. Meetings\n * already recorded stay listed, and a recording already underway keeps its controls.\n */\n recordingOff?: ReactNode;\n /** The person recording's name, for their microphone's live text beside computer or tab audio. */\n viewerName?: string | null;\n}) {\n const msg = useOpenGeniText();\n const columns: RowListColumn[] = [\n { id: \"length\", label: msg(\"meetings.listPage.length\"), width: 96 },\n { id: \"recorded\", label: msg(\"meetings.listPage.recorded\"), width: 148 },\n ];\n const [search, setSearch] = useState(\"\");\n const query = useDebounced(search.trim(), 250);\n const override = { workspaceId, ...(recordingsClient ? { recordings: recordingsClient } : {}) };\n const list = useRecordings({\n ...override,\n ...(query ? { query } : {}),\n ...(externalRef ? { externalRef } : {}),\n });\n const { client } = useRecordingsClient(override);\n const {\n recorder,\n finished,\n workspaceId: recorderWorkspaceId,\n openMeeting,\n } = useMeetingRecorder();\n const online = useOnline();\n // A recording started in another workspace keeps going here; its meeting\n // opens in its own workspace.\n const openRecorded = useCallback(\n (recordingId: string) => {\n if (\n recorderWorkspaceId &&\n recorderWorkspaceId !== workspaceId &&\n openMeeting(recordingId, recorderWorkspaceId)\n ) {\n return;\n }\n onOpen(recordingId);\n },\n [recorderWorkspaceId, workspaceId, openMeeting, onOpen],\n );\n const models = useRecordingModels(override);\n const liveModel = models.liveModels.find((entry) => entry.available) ?? null;\n // A desktop call notification's Record waits for the live model list, so\n // the recording gets the same live-preview default as a click on Start.\n const pendingStart = usePendingMeetingStart();\n const autoStart = useMemo(\n () => ({ pending: pendingStart.request !== null && !models.loading, take: pendingStart.take }),\n [pendingStart.request, pendingStart.take, models.loading],\n );\n const narrow = useNarrow();\n const [pendingDelete, setPendingDelete] = useState<Recording | null>(null);\n\n // A recording that finished uploading in this tab changes state on the server.\n const refresh = list.refresh;\n const finishedCount = finished.length;\n useEffect(() => {\n if (finishedCount > 0) void refresh();\n }, [finishedCount, refresh]);\n // A recording that just started shows up in the list as soon as the server has it.\n const liveId = recorder?.upload?.created ? recorder.recordingId : null;\n const lastLiveId = useRef<string | null>(null);\n useEffect(() => {\n if (liveId && liveId !== lastLiveId.current) {\n lastLiveId.current = liveId;\n void refresh();\n }\n }, [liveId, refresh]);\n\n const loading = list.loading && list.recordings.length === 0;\n const empty = !list.loading && !list.error && list.recordings.length === 0;\n const showRecorder = recordingOff === null || (recorder !== null && recorder.state !== \"idle\");\n\n return (\n <>\n {header ? (\n <PageHeader\n icon={<AudioLinesIcon />}\n title={msg(\"meetings.listPage.meetings\")}\n description={msg(\"meetings.listPage.recordAMeetingAndGet\")}\n />\n ) : null}\n <div className={header ? \"mt-2 grid gap-8\" : \"grid gap-8\"}>\n {showRecorder ? (\n <RecorderPanel\n recorder={recorder}\n onStopped={openRecorded}\n onOpenNotes={openRecorded}\n defaultLanguage={defaultLanguage !== undefined ? defaultLanguage : models.language}\n autoStart={autoStart}\n externalRef={externalRef}\n notice={notice}\n viewerName={viewerName}\n liveTranscript={\n liveTranscript && liveModel\n ? {\n defaultOn: liveTranscriptDefault ?? models.liveTranscript ?? false,\n usdPerHour: liveModel.usdPerHour,\n }\n : null\n }\n />\n ) : (\n <Notice tone=\"info\">{recordingOff}</Notice>\n )}\n {recorder && recorder.recovered.length > 0 ? (\n <Notice tone=\"info\">\n {msg(\"meetings.listPage.earlierRecordingsWereStillSaved\", {\n count: recorder.recovered.length,\n })}\n </Notice>\n ) : null}\n <div className=\"grid gap-3\">\n {list.recordings.length > 0 || query ? (\n <div className=\"relative max-w-80\">\n <SearchIcon\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-fg-subtle\"\n />\n <Input\n type=\"search\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n placeholder={msg(\"meetings.listPage.searchMeetings\")}\n aria-label={msg(\"meetings.listPage.searchMeetings\")}\n className=\"h-9 pl-9 pointer-coarse:h-11\"\n />\n </div>\n ) : null}\n {loading ? (\n <RowList\n label={msg(\"meetings.listPage.meetings\")}\n columns={narrow ? [] : columns}\n flush\n busy\n >\n <ListRowSkeleton count={4} />\n </RowList>\n ) : list.error && list.recordings.length === 0 ? (\n <ErrorMessage\n align=\"center\"\n title={msg(\"meetings.listPage.couldnTLoadMeetings\")}\n details={[{ label: msg(\"meetings.listPage.error\"), value: list.error.message }]}\n action={\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void list.refresh()}\n className=\"pointer-coarse:h-11\"\n >\n {msg(\"meetings.listPage.tryAgain\")}\n </Button>\n }\n >\n {msg(\"meetings.listPage.checkYourConnectionThenTry\")}\n </ErrorMessage>\n ) : empty ? (\n query ? (\n <EmptyState\n variant=\"inline\"\n title={msg(\"meetings.listPage.noMeetingsMatchQuery\", { query: query })}\n description={msg(\"meetings.listPage.searchFindsWordsInMeeting\")}\n />\n ) : (\n <EmptyState\n variant=\"page\"\n icon={<AudioLinesIcon />}\n title={msg(\"meetings.listPage.noMeetingsYet\")}\n description={\n showRecorder ? msg(\"meetings.listPage.startARecordingAboveWhen\") : undefined\n }\n className=\"pt-8\"\n />\n )\n ) : (\n <RowList\n label={msg(\"meetings.listPage.meetings\")}\n columns={narrow ? [] : columns}\n flush\n >\n {list.recordings.map((recording) => {\n // Stopped here, its last audio is on its way: Transcribing, not In progress.\n const here =\n recording.state === \"capturing\"\n ? meetingHereStatus(recorder, recording.id, online)\n : null;\n const status = meetingStatusLabel(\n here === \"transcribing\"\n ? { kind: \"transcribing\", version: null }\n : meetingPhase(recording),\n msg,\n );\n // Recording here until Stop: after it, the row reads Transcribing.\n const isLive = here === \"recording\" || here === \"paused\";\n return (\n <ListRow\n key={recording.id}\n leading={<LogoTile icon={<AudioLinesIcon />} />}\n title={meetingTitle(recording, msg)}\n titleAddon={\n recording.sourceWorkspace ? (\n // The person's own Only me meeting, stored in another\n // workspace of the organization: say which.\n <MetaChip icon={<LockIcon />}>\n <span className=\"sr-only\">\n {msg(\"meetings.listPage.onlyMeRecordedIn\", {\n workspace: recording.sourceWorkspace.name,\n })}\n </span>\n <span aria-hidden=\"true\">{recording.sourceWorkspace.name}</span>\n </MetaChip>\n ) : recording.visibility === \"private\" ? (\n <MetaChip icon={<LockIcon />}>\n <span className={narrow ? \"sr-only\" : undefined}>\n {msg(\"meetings.listPage.onlyMe\")}\n </span>\n </MetaChip>\n ) : undefined\n }\n status={\n isLive ? (\n here === \"paused\" ? (\n <StatusBadge variant=\"dot\" tone=\"neutral\">\n {msg(\"meetings.recorderPanel.paused\")}\n </StatusBadge>\n ) : (\n <StatusBadge variant=\"dot\" tone=\"danger\" pulse>\n {msg(\"meetings.listPage.recording\")}\n </StatusBadge>\n )\n ) : status ? (\n <StatusBadge\n variant=\"dot\"\n tone={status.tone}\n pulse={status.tone === \"progress\"}\n >\n {status.label}\n </StatusBadge>\n ) : undefined\n }\n meta={\n narrow\n ? [\n <RelativeTime key=\"recorded\" date={recording.startedAt} />,\n recording.durationMilliseconds > 0\n ? formatDuration(recording.durationMilliseconds, msg)\n : null,\n ].filter(Boolean)\n : undefined\n }\n cells={{\n length:\n recording.durationMilliseconds > 0 ? (\n <span className=\"tabular-nums\">\n {formatDuration(recording.durationMilliseconds, msg)}\n </span>\n ) : (\n <span className=\"text-fg-subtle\">—</span>\n ),\n recorded: <RelativeTime date={recording.startedAt} />,\n }}\n menu={\n <DropdownMenuItem\n variant=\"destructive\"\n onSelect={() => setPendingDelete(recording)}\n >\n <Trash2Icon aria-hidden=\"true\" />\n {msg(\"meetings.listPage.deleteMeeting\")}\n </DropdownMenuItem>\n }\n menuLabel={msg(\"meetings.listPage.moreActionsForTitle\", {\n title: meetingTitle(recording, msg),\n })}\n href={meetingHref(recording.id)}\n linkProps={{ onClick: inAppClick(() => onOpen(recording.id)) }}\n />\n );\n })}\n </RowList>\n )}\n {list.hasMore ? (\n <div className=\"flex justify-center\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={list.loadingMore}\n onClick={() => void list.loadMore()}\n className=\"pointer-coarse:h-11\"\n >\n {list.loadingMore\n ? msg(\"meetings.listPage.loading\")\n : msg(\"meetings.listPage.showOlderMeetings\")}\n </Button>\n </div>\n ) : null}\n </div>\n </div>\n <DeleteMeetingDialog\n recording={\n pendingDelete && { id: pendingDelete.id, title: meetingTitle(pendingDelete, msg) }\n }\n onClose={() => setPendingDelete(null)}\n onDelete={async (recordingId) => {\n await client.deleteRecording(workspaceId, recordingId);\n }}\n onDeleted={() => void list.refresh()}\n />\n </>\n );\n}\n\nexport function MeetingsListPage(props: ComponentProps<typeof MeetingsListPageContent>) {\n return (\n <MeetingsOverlayScope>\n <MeetingsListPageContent {...props} />\n </MeetingsOverlayScope>\n );\n}\n","import type { ComponentProps } from \"react\";\nimport { useOpenGeniText } from \"../messages/runtime\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\nimport type { Recording } from \"@opengeni/contracts\";\n\nimport { ConfirmDialog } from \"../ui/confirm-dialog\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\n\nfunction DeleteMeetingDialogContent({\n recording,\n onClose,\n onDelete,\n onDeleted,\n}: {\n recording: Pick<Recording, \"id\" | \"title\"> | null;\n onClose: () => void;\n onDelete: (recordingId: string) => Promise<void>;\n onDeleted: () => void;\n}) {\n const msg = useOpenGeniText();\n return (\n <ConfirmDialog\n open={recording !== null}\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n title={\n recording\n ? msg(\"meetings.deleteDialog.deleteTitle\", { title: recording.title })\n : msg(\"meetings.deleteDialog.deleteMeeting\")\n }\n description={msg(\"meetings.deleteDialog.thisDeletesTheAudioEvery\")}\n confirmLabel={msg(\"meetings.deleteDialog.deleteMeeting2\")}\n pendingLabel={msg(\"meetings.deleteDialog.deleting\")}\n onConfirm={async () => {\n if (!recording) return;\n try {\n await onDelete(recording.id);\n } catch (error) {\n toast.error(msg(\"meetings.deleteDialog.couldnTDeleteThisMeeting\"), {\n description: error instanceof Error ? userErrorText(error) : undefined,\n });\n return false;\n }\n toast.success(msg(\"meetings.deleteDialog.meetingDeleted\"));\n onDeleted();\n }}\n />\n );\n}\n\n/** \"Delete 'Weekly sync'?\": removes the audio, every transcript and the speaker names. */\nexport function DeleteMeetingDialog(props: ComponentProps<typeof DeleteMeetingDialogContent>) {\n return (\n <MeetingsOverlayScope>\n <DeleteMeetingDialogContent {...props} />\n </MeetingsOverlayScope>\n );\n}\n","/**\n * One meeting's own page: back to Meetings, the title with who can see it,\n * Summary · Transcript · Notepad under it, then the player and the open tab.\n * Summary is the written notes (with mention chips and Copy), Transcript the\n * turns as speaker bubbles, Notepad what people jotted down; Summary and\n * Transcript end with \"Ask about this meeting\" when the host answers it. The\n * quiet card on the right names the speakers and says which transcript\n * version this is, with Transcribe again.\n *\n * Until the transcript exists the page says where the meeting is: still\n * recording here (with Pause and Stop, so taking notes never hides it), not\n * finished yet on another device, transcribing, or failed with the reason and\n * what to try. Audio uploads while it records, so after Stop it reads\n * Transcribing, not Uploading.\n */\nimport { useOpenGeniText, createOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\nimport { regionRestrictedText } from \"../inference-region\";\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport {\n AudioLinesIcon,\n CheckIcon,\n ChevronDownIcon,\n CreditCardIcon,\n GlobeIcon,\n LayersIcon,\n LoaderCircleIcon,\n LockIcon,\n PencilIcon,\n RefreshCwIcon,\n Trash2Icon,\n} from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\nimport type {\n Recording,\n RecordingNote,\n RecordingPerson,\n RecordingTranscriptVersion,\n RecordingTranscriptionModel,\n RecordingVisibility,\n} from \"@opengeni/contracts\";\nimport {\n activeSegmentIndex,\n defaultSpeakerName,\n formatDuration,\n languageName,\n meetingHereStatus,\n meetingPhase,\n meetingUploadFailure,\n ownerLiveLaneName,\n speakerColorSlots,\n speakerDisplayName,\n speakerIsNamed,\n meetingTitle,\n transcribingText,\n transcriptErrorText,\n transcriptFixModel,\n transcriptNeedsCredits,\n useRecording,\n useRecordingModels,\n useRecordingNotes,\n useRecordingPeople,\n useRecordingsClient,\n useLiveTranscript,\n useTranscript,\n type MeetingHereStatus,\n type RecordingsClientOverride,\n} from \"../recordings\";\n\nimport { Button } from \"../ui/button\";\nimport { ConfirmDialog } from \"../ui/confirm-dialog\";\nimport {\n DetailAside,\n DetailAsideItem,\n DetailMeta,\n DetailPage,\n DetailPageBody,\n DetailPageHeader,\n} from \"../ui/detail-page\";\nimport { DetailSection } from \"../ui/detail-sheet\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"../ui/dropdown-menu\";\nimport { EmptyState } from \"../ui/empty-state\";\nimport { ErrorMessage } from \"../ui/error-message\";\nimport { Field, FieldStack, TextInput } from \"../ui/field\";\nimport { FormDialog } from \"../ui/form-dialog\";\nimport { MoreMenu } from \"../ui/page-actions\";\nimport { Notice } from \"../ui/notice\";\nimport { formatAbsoluteTime } from \"../ui/relative-time\";\nimport { SegmentedControl } from \"../ui/segmented-control\";\nimport { NativeSelect, type SelectOption } from \"../ui/select-menu\";\nimport { Skeleton } from \"../ui/skeleton\";\nimport { cn } from \"../app/lib/utils\";\nimport {\n WorkspaceReachFields,\n type ReachWorkspace,\n type WorkspaceReach,\n} from \"../app/components/workspace-reach\";\n\nimport { DeleteMeetingDialog } from \"./delete-meeting-dialog\";\nimport { DETECT_LANGUAGE, meetingLanguageOptions } from \"./meeting-languages\";\nimport {\n MeetingPlayer,\n type MeetingPlayerHandle,\n type MeetingPlayerSource,\n} from \"./meeting-player\";\nimport {\n MeetingTranscript,\n NewSpeakerNameDialog,\n SpeakerDot,\n SpeakerNameMenu,\n speakerIsSuggested,\n type TranscriptActions,\n} from \"./meeting-transcript\";\nimport { liveSpeakerName, RecordingBar, recorderLiveLines, useOnline } from \"./recorder-panel\";\nimport { LiveTranscript, liveStatus } from \"./live-transcript\";\nimport { MeetingAsk, type MeetingAskRequest, type MeetingAskResult } from \"./meeting-ask\";\nimport { meetingMentionResolver } from \"./meeting-mentions\";\nimport { useAnnounceMeetingOnScreen } from \"./meeting-on-screen\";\nimport { useUiEventTarget } from \"../app/lib/ui-events\";\nimport { MeetingNotepad, MeetingNotesSection, MeetingSummary } from \"./meeting-notes\";\nimport { useMeetingRecorder, type MeetingRecorder } from \"./recorder-context\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\nimport { StickyBarEdge, useStuckToTop } from \"./sticky-bar-edge\";\n\nconst defaultText = createOpenGeniText();\n\nfunction errorText(error: unknown): string | undefined {\n return error instanceof Error ? userErrorText(error) : undefined;\n}\n\nfunction isNotFound(error: Error | null): boolean {\n return Boolean(error && /not found|404/iu.test(error.message));\n}\n\n/**\n * Fresh playback links for every prepared track. Links expire, so a failed one refetches.\n * While the meeting is processed, the player waits until every recorded track can\n * play: the first track alone sounds as if the rest (the call's side) was never recorded.\n */\nfunction useTrackSources(\n recording: Recording | null,\n getAudio: (trackNumber: number) => Promise<{ url: string }>,\n): { sources: MeetingPlayerSource[]; reload: () => void } {\n const [sources, setSources] = useState<MeetingPlayerSource[]>([]);\n const [generation, setGeneration] = useState(0);\n const state = recording?.state;\n const playable = useMemo(() => {\n const tracks = recording?.tracks ?? [];\n const partial =\n state === \"processing\" && tracks.some((track) => track.chunkCount > 0 && !track.playable);\n return partial\n ? []\n : tracks.filter((track) => track.playable).map((track) => track.trackNumber);\n }, [recording?.tracks, state]);\n const key = playable.join(\",\");\n const getAudioRef = useRef(getAudio);\n getAudioRef.current = getAudio;\n useEffect(() => {\n if (!key) {\n setSources([]);\n return;\n }\n let cancelled = false;\n void Promise.all(\n key.split(\",\").map(async (value) => {\n const trackNumber = Number(value);\n try {\n const audio = await getAudioRef.current(trackNumber);\n return { trackNumber, url: audio.url };\n } catch {\n return null;\n }\n }),\n ).then((loaded) => {\n if (!cancelled) {\n setSources(loaded.filter((source): source is MeetingPlayerSource => source !== null));\n }\n });\n return () => {\n cancelled = true;\n };\n }, [key, generation]);\n const reload = useCallback(() => setGeneration((value) => value + 1), []);\n return { sources, reload };\n}\n\nfunction RenameDialog({\n open,\n title,\n onClose,\n onRename,\n}: {\n open: boolean;\n title: string;\n onClose: () => void;\n onRename: (title: string) => Promise<void>;\n}) {\n const msg = useOpenGeniText();\n const [value, setValue] = useState(title);\n const [error, setError] = useState<string | null>(null);\n useEffect(() => {\n if (open) {\n setValue(title);\n setError(null);\n }\n }, [open, title]);\n return (\n <FormDialog\n open={open}\n onOpenChange={(next) => {\n if (!next) onClose();\n }}\n title={msg(\"meetings.detailPage.renameMeeting\")}\n submitLabel={msg(\"meetings.detailPage.save\")}\n pendingLabel={msg(\"meetings.detailPage.saving\")}\n submitDisabled={!value.trim() || value.trim() === title}\n error={error}\n onSubmit={async () => {\n try {\n await onRename(value.trim());\n } catch (cause) {\n setError(errorText(cause) ?? msg(\"meetings.detailPage.couldnTRenameThisMeeting\"));\n return false;\n }\n }}\n onSubmitted={onClose}\n >\n <FieldStack>\n <Field label={msg(\"meetings.detailPage.title\")}>\n <TextInput\n value={value}\n maxLength={300}\n onChange={(event) => setValue(event.target.value)}\n />\n </Field>\n </FieldStack>\n </FormDialog>\n );\n}\n\n/**\n * Where the owner's own Only me meeting works: the workspace that stores it\n * and their Personal workspace always, plus the ones they pick, or all of\n * their workspaces in the organization. Only they, and agent turns they\n * start, see it in any of them.\n */\nfunction MeetingReachDialog({\n open,\n recording,\n hereId,\n workspaces,\n organizationName,\n onClose,\n onSave,\n}: {\n open: boolean;\n recording: Recording;\n /** The workspace the page was opened from. */\n hereId: string;\n workspaces: readonly ReachWorkspace[];\n organizationName: string;\n onClose: () => void;\n /** Saves the other workspaces it works in (null for all), and says whether it still works here. */\n onSave: (reachWorkspaceIds: string[] | null, leavesHere: boolean) => Promise<void>;\n}) {\n const msg = useOpenGeniText();\n const saved = recording.reachWorkspaceIds ?? null;\n const savedKey = saved === null ? null : saved.join(\",\");\n const [value, setValue] = useState<WorkspaceReach>({\n workspaceIds: saved,\n personalWorkspaces: true,\n });\n const [error, setError] = useState<string | null>(null);\n useEffect(() => {\n if (open) {\n setValue({\n workspaceIds: savedKey === null ? null : savedKey.split(\",\").filter(Boolean),\n personalWorkspaces: true,\n });\n setError(null);\n }\n }, [open, savedKey]);\n const home = recording.workspaceId;\n const here = workspaces.find((workspace) => workspace.id === hereId);\n const chosen =\n value.workspaceIds === null ? null : value.workspaceIds.filter((id) => id !== home).sort();\n // Opened from another workspace it was turned on in, which it would leave.\n const leavesHere =\n hereId !== home && here?.personal !== true && chosen !== null && !chosen.includes(hereId);\n const unchanged =\n chosen === null\n ? saved === null\n : saved !== null && [...saved].sort().join(\",\") === chosen.join(\",\");\n return (\n <FormDialog\n open={open}\n onOpenChange={(next) => {\n if (!next) onClose();\n }}\n title={msg(\"meetings.detailPage.availableIn\")}\n description={msg(\"meetings.detailPage.onlyYouSeeItInThese\")}\n submitLabel={msg(\"meetings.detailPage.save\")}\n pendingLabel={msg(\"meetings.detailPage.saving\")}\n submitDisabled={unchanged}\n error={error}\n onSubmit={async () => {\n try {\n await onSave(chosen, leavesHere);\n } catch (cause) {\n setError(errorText(cause) ?? msg(\"meetings.detailPage.couldnTChangeWhereItWorks\"));\n return false;\n }\n }}\n onSubmitted={onClose}\n >\n <div className=\"flex min-w-0 flex-col gap-4\">\n <WorkspaceReachFields\n owner={{ kind: \"person\" }}\n organizationName={organizationName}\n label={msg(\"meetings.detailPage.availableIn\")}\n labelHidden\n value={value}\n onChange={setValue}\n workspaces={workspaces}\n hereId={hereId}\n alwaysIncluded={{ [home]: msg(\"meetings.detailPage.recordedThereAlwaysIncluded\") }}\n // Switching from All keeps the workspace it was opened from.\n seedSelected={() => (hereId !== home && here?.personal !== true ? [hereId] : [])}\n personalWorkspaces=\"always\"\n />\n {leavesHere ? (\n <Notice tone=\"info\" live=\"polite\">\n {msg(\"meetings.detailPage.itWillNoLongerShowHere\")}\n </Notice>\n ) : null}\n </div>\n </FormDialog>\n );\n}\n\n/**\n * The models \"Transcribe again\" offers. One that can't be used says why:\n * \"Not supported in EU\" when EU-only switched it off, otherwise what to connect.\n */\nexport function transcribeAgainModelOptions(\n models: readonly Pick<\n RecordingTranscriptionModel,\n | \"providerId\"\n | \"providerName\"\n | \"model\"\n | \"name\"\n | \"available\"\n | \"unavailableReason\"\n | \"usdPerHour\"\n >[],\n msg: OpenGeniText = defaultText,\n): SelectOption[] {\n return models.map((entry) => ({\n value: `${entry.providerId}/${entry.model}`,\n label: entry.name,\n meta:\n entry.usdPerHour !== null\n ? msg(\"meetings.detailPage.valuePerHour\", { value: entry.usdPerHour.toFixed(2) })\n : entry.providerName,\n disabled: !entry.available,\n disabledReason: entry.available\n ? undefined\n : (regionRestrictedText(msg, entry.unavailableReason) ??\n msg(\"meetings.detailPage.connectProvidernameFirst\", { providerName: entry.providerName })),\n }));\n}\n\n/**\n * What transcribing a meeting again costs at a model's hourly price. Each\n * recorded track (a microphone beside computer audio, say) is transcribed and\n * billed on its own, so a two-track hour costs two hours.\n */\nexport function transcribeAgainEstimate(\n recording: Pick<Recording, \"durationMilliseconds\" | \"tracks\">,\n usdPerHour: number | null | undefined,\n): { usd: number; tracks: number } | null {\n if (usdPerHour == null) return null;\n const recorded = recording.tracks.filter(\n (track) => track.chunkCount > 0 && track.durationMilliseconds > 0,\n );\n const milliseconds =\n recorded.length > 0\n ? recorded.reduce((total, track) => total + track.durationMilliseconds, 0)\n : recording.durationMilliseconds;\n if (milliseconds <= 0) return null;\n return { usd: (usdPerHour * milliseconds) / 3_600_000, tracks: Math.max(1, recorded.length) };\n}\n\nfunction TranscribeAgainDialog({\n open,\n recording,\n models,\n defaultModel,\n onClose,\n onRun,\n}: {\n open: boolean;\n recording: Recording;\n models: ReturnType<typeof useRecordingModels>[\"models\"];\n defaultModel: ReturnType<typeof useRecordingModels>[\"defaultModel\"];\n onClose: () => void;\n onRun: (options: {\n providerId: string;\n model: string;\n /** Null detects it, even when the workspace names a meeting language. */\n language: string | null;\n /** How many people speak; speaker detection finds that many. */\n speakers?: number;\n }) => Promise<void>;\n}) {\n const msg = useOpenGeniText();\n const current = recording.transcript;\n const initialModel = current\n ? `${current.providerId}/${current.model}`\n : defaultModel\n ? `${defaultModel.providerId}/${defaultModel.model}`\n : \"\";\n const [model, setModel] = useState(initialModel);\n const [language, setLanguage] = useState<string>(\n recording.transcription.language ?? DETECT_LANGUAGE,\n );\n const initialSpeakers = recording.transcription.speakers ?? recording.transcription.maxSpeakers;\n const [speakers, setSpeakers] = useState(initialSpeakers ? String(initialSpeakers) : \"\");\n const [error, setError] = useState<string | null>(null);\n useEffect(() => {\n if (open) {\n setModel(initialModel);\n setError(null);\n }\n }, [open, initialModel]);\n const modelOptions = transcribeAgainModelOptions(models, msg);\n const selected = models.find((entry) => `${entry.providerId}/${entry.model}` === model);\n const estimate = transcribeAgainEstimate(recording, selected?.usdPerHour);\n const duration = formatDuration(recording.durationMilliseconds, msg);\n const languageOptions = meetingLanguageOptions(language, undefined, msg);\n const speakerCount = speakers.trim() ? Number(speakers) : undefined;\n const speakersInvalid =\n speakerCount !== undefined &&\n (!Number.isInteger(speakerCount) || speakerCount < 1 || speakerCount > 32);\n // Speakers come from the model, or from Opengeni's own speaker detection\n // when this deployment has it (it made the current transcript's).\n const tellsSpeakersApart =\n selected?.capabilities.diarization === true || current?.diarization === \"ours\";\n return (\n <FormDialog\n open={open}\n onOpenChange={(next) => {\n if (!next) onClose();\n }}\n title={msg(\"meetings.detailPage.transcribeAgain\")}\n description={msg(\"meetings.detailPage.makesANewTranscriptNotesToo\")}\n submitLabel={msg(\"meetings.detailPage.transcribe\")}\n pendingLabel={msg(\"meetings.detailPage.starting\")}\n submitDisabled={!selected || !selected.available || speakersInvalid}\n error={error}\n onSubmit={async () => {\n if (!selected) return false;\n try {\n await onRun({\n providerId: selected.providerId,\n model: selected.model,\n language: language === DETECT_LANGUAGE ? null : language,\n ...(speakerCount !== undefined && tellsSpeakersApart ? { speakers: speakerCount } : {}),\n });\n } catch (cause) {\n setError(errorText(cause) ?? msg(\"meetings.detailPage.couldnTStartTranscribing\"));\n return false;\n }\n }}\n onSubmitted={onClose}\n >\n <FieldStack>\n <Field\n label={msg(\"meetings.detailPage.model\")}\n hint={\n estimate !== null\n ? estimate.usd < 0.01\n ? msg(\"meetings.detailPage.aboutLessThan001\", { duration })\n : estimate.tracks > 1\n ? msg(\"meetings.detailPage.aboutEstimateForTracks\", {\n estimate: estimate.usd.toFixed(2),\n duration,\n count: estimate.tracks,\n })\n : msg(\"meetings.detailPage.aboutEstimateForThisDuration\", {\n estimate: estimate.usd.toFixed(2),\n duration,\n })\n : undefined\n }\n >\n <NativeSelect options={modelOptions} value={model} onValueChange={setModel} />\n </Field>\n <Field\n label={msg(\"meetings.detailPage.language\")}\n hint={msg(\"meetings.detailPage.setItWhenTheMeeting\")}\n >\n <NativeSelect options={languageOptions} value={language} onValueChange={setLanguage} />\n </Field>\n {tellsSpeakersApart ? (\n <Field\n label={msg(\"meetings.detailPage.numberOfSpeakers\")}\n optional\n hint={msg(\"meetings.detailPage.leaveEmptyToLetThe\")}\n error={speakersInvalid ? msg(\"meetings.detailPage.enterAWholeNumberFrom\") : undefined}\n >\n <TextInput\n inputMode=\"numeric\"\n value={speakers}\n placeholder={msg(\"meetings.detailPage.auto\")}\n onChange={(event) => setSpeakers(event.target.value.replace(/[^0-9]/gu, \"\"))}\n className=\"max-w-24\"\n />\n </Field>\n ) : null}\n </FieldStack>\n </FormDialog>\n );\n}\n\nfunction VisibilityMenu({\n visibility,\n onChange,\n}: {\n visibility: RecordingVisibility;\n onChange: (visibility: RecordingVisibility) => void;\n}) {\n const msg = useOpenGeniText();\n const options: Array<{ value: RecordingVisibility; label: string; description: string }> = [\n {\n value: \"private\",\n label: msg(\"meetings.detailPage.onlyMe\"),\n description: msg(\"meetings.detailPage.onlyYouCanOpenIt\"),\n },\n {\n value: \"workspace\",\n label: msg(\"meetings.detailPage.workspace\"),\n description: msg(\"meetings.detailPage.everyoneInThisWorkspaceCan\"),\n },\n ];\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"rounded-[10px] pointer-coarse:h-11\"\n aria-label={msg(\"meetings.detailPage.whoCanSeeThisValue\", {\n value:\n visibility === \"private\"\n ? msg(\"meetings.detailPage.onlyMe\")\n : msg(\"meetings.detailPage.workspace\"),\n })}\n >\n {visibility === \"private\" ? (\n <LockIcon aria-hidden=\"true\" />\n ) : (\n <GlobeIcon aria-hidden=\"true\" />\n )}\n {visibility === \"private\"\n ? msg(\"meetings.detailPage.onlyMe\")\n : msg(\"meetings.detailPage.workspace\")}\n <ChevronDownIcon aria-hidden=\"true\" className=\"text-fg-subtle\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-64\">\n {options.map((option) => (\n <DropdownMenuItem\n key={option.value}\n onSelect={() => {\n if (option.value !== visibility) onChange(option.value);\n }}\n className=\"items-start\"\n >\n <span className=\"grid min-w-0 flex-1 gap-0.5\">\n <span className=\"text-sm leading-5 text-fg\">{option.label}</span>\n <span className=\"text-xs leading-4.5 text-fg-muted\">{option.description}</span>\n </span>\n {option.value === visibility ? (\n <CheckIcon aria-hidden=\"true\" className=\"mt-0.5 text-brand\" />\n ) : null}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\n/** A transcript version's model and the provider it runs on, by name. */\ntype ModelAbout = {\n modelName: string;\n providerName: string;\n funding: string;\n /** The deployment offers no other model. */\n pinned: boolean;\n};\n\nconst SPINNER = (\n <LoaderCircleIcon aria-hidden=\"true\" className=\"size-4 animate-spin motion-reduce:animate-none\" />\n);\n\n/** What fixes a failed transcript, besides transcribing it again from the dialog. */\ntype TranscriptFixes = {\n /** The models this workspace can transcribe with, to pick the direct fix from. */\n models: readonly RecordingTranscriptionModel[];\n /** Transcribe it now with another model, the one-click fix. */\n onTranscribeWith: (model: RecordingTranscriptionModel) => Promise<void>;\n /** Opens where credits are bought; absent when this person can't buy them. */\n onOpenBilling?: (() => void) | undefined;\n /** Opens where models are connected; absent when this person can't connect them. */\n onConnectModels?: (() => void) | undefined;\n};\n\n/**\n * A failed transcript's actions: one direct fix (another model that works\n * here, else adding credits or connecting a model), then Transcribe again,\n * which tries once more with any model once the cause is fixed.\n */\nfunction FailedTranscriptActions({\n version,\n about,\n fixes,\n onRetry,\n}: {\n version: RecordingTranscriptVersion | null;\n about: ModelAbout | null;\n fixes: TranscriptFixes;\n onRetry: () => void;\n}) {\n const msg = useOpenGeniText();\n const [running, setRunning] = useState(false);\n const code = version?.errorCode ?? null;\n const switchTo = transcriptFixModel(code, version, fixes.models);\n const connect =\n !switchTo &&\n (code === \"missing_provider_key\" || code === \"provider_unauthorized\") &&\n about?.funding !== \"deployment\"\n ? fixes.onConnectModels\n : undefined;\n const billing = !switchTo && transcriptNeedsCredits(code) ? fixes.onOpenBilling : undefined;\n return (\n <span className=\"flex flex-wrap gap-2\">\n {switchTo ? (\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={running}\n onClick={() => {\n setRunning(true);\n void fixes\n .onTranscribeWith(switchTo)\n .catch((error: unknown) => {\n toast.error(msg(\"meetings.detailPage.couldnTStartTranscribing\"), {\n description: errorText(error),\n });\n })\n .finally(() => setRunning(false));\n }}\n >\n {running ? SPINNER : null}\n {msg(\"meetings.detailPage.transcribeWithModel\", { modelName: switchTo.name })}\n </Button>\n ) : billing ? (\n <Button type=\"button\" size=\"sm\" onClick={billing}>\n <CreditCardIcon aria-hidden=\"true\" />\n {msg(\"meetings.detailPage.addCredits\")}\n </Button>\n ) : connect ? (\n <Button type=\"button\" size=\"sm\" onClick={connect}>\n {msg(\"meetings.detailPage.connectAModel\")}\n </Button>\n ) : null}\n <Button type=\"button\" size=\"sm\" variant=\"outline\" disabled={running} onClick={onRetry}>\n {msg(\"meetings.detailPage.transcribeAgain\")}\n </Button>\n </span>\n );\n}\n\n/** Why an upload failed, in the words of a transcript failure when it has the same cause. */\nfunction uploadFailureText(\n failure: { code: string; message: string } | null,\n msg: OpenGeniText,\n): string {\n if (!failure) return msg(\"meetings.detailPage.theAudioCouldnTBeUploaded\");\n if (transcriptNeedsCredits(failure.code)) return transcriptErrorText(failure.code, msg);\n // The notice's title already says the upload failed; the server's reason\n // reads as the first sentence of its text.\n const reason = failure.message.trim();\n if (!reason) return msg(\"meetings.detailPage.theAudioCouldnTBeUploaded\");\n return /[.!?]$/.test(reason) ? reason : `${reason}.`;\n}\n\nfunction PhaseNotice({\n recording,\n recorder,\n here,\n recordingElsewhere,\n modelOf,\n fixes,\n onRetry,\n}: {\n recording: Recording;\n recorder: MeetingRecorder | null;\n /** What this device's recorder knows about the meeting; null when it isn't recording it. */\n here: MeetingHereStatus | null;\n /** It's captured on another device with the live preview on. */\n recordingElsewhere: boolean;\n /** The version's model and its provider, when the workspace's list has it. */\n modelOf: (version: RecordingTranscriptVersion) => ModelAbout | null;\n fixes: TranscriptFixes;\n onRetry: () => void;\n}) {\n const msg = useOpenGeniText();\n const phase = meetingPhase(recording);\n if (phase.kind === \"uploading\" && recorder && (here === \"recording\" || here === \"paused\")) {\n return <RecordingBar recorder={recorder} />;\n }\n if (phase.kind === \"uploading\" && here === \"waiting_for_connection\") {\n return (\n <Notice tone=\"waiting\" live=\"polite\">\n {msg(\"meetings.recorderPanel.notUploadingNoConnectionThe\")}\n </Notice>\n );\n }\n if (phase.kind === \"uploading\" && recorder && here === \"upload_failed\") {\n // The audio stays on this device: once the cause is fixed, the same upload carries on.\n return (\n <Notice\n tone=\"failed\"\n title={msg(\"meetings.detailPage.theUploadDidnTFinish\")}\n live=\"polite\"\n actionLayout=\"responsive\"\n action={\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n // The uploader holding it was closed: reloading starts a new one.\n if (!recorder.retryUpload(recording.id)) {\n toast.error(msg(\"meetings.detailPage.couldnTTryAgainReload\"));\n }\n }}\n >\n {msg(\"meetings.detailPage.tryAgain\")}\n </Button>\n }\n >\n {msg(\"meetings.detailPage.uploadFailureKeptHere\", {\n reason: uploadFailureText(meetingUploadFailure(recorder, recording.id), msg),\n })}\n </Notice>\n );\n }\n if (phase.kind === \"uploading\" && here === \"uploading\") {\n return (\n <Notice tone=\"waiting\" icon={SPINNER} live=\"polite\">\n {msg(\"meetings.detailPage.uploadingFromThisDevice\")}\n </Notice>\n );\n }\n if (phase.kind === \"uploading\" && here !== \"transcribing\") {\n // Nothing on this device can move it along: say where the audio is and what finishes it.\n return recordingElsewhere ? (\n <Notice\n tone=\"waiting\"\n icon={SPINNER}\n title={msg(\"meetings.detailPage.notFinishedYet\")}\n live=\"polite\"\n >\n {msg(\"meetings.detailPage.itSStillBeingRecorded\")}\n </Notice>\n ) : (\n <Notice tone=\"waiting\" title={msg(\"meetings.detailPage.notFinishedYet\")} live=\"polite\">\n {msg(\"meetings.detailPage.theAudioIsOnThe\")}\n </Notice>\n );\n }\n if (phase.kind === \"transcribing\" || phase.kind === \"uploading\") {\n return (\n <Notice tone=\"waiting\" icon={SPINNER} live=\"polite\">\n {transcribingText(recording.durationMilliseconds, msg)}\n </Notice>\n );\n }\n if (phase.kind === \"failed\") {\n const about = phase.version ? modelOf(phase.version) : null;\n return (\n <Notice\n tone=\"failed\"\n title={msg(\"meetings.detailPage.theTranscriptFailed\")}\n actionLayout=\"responsive\"\n action={\n <FailedTranscriptActions\n version={phase.version}\n about={about}\n fixes={fixes}\n onRetry={onRetry}\n />\n }\n >\n {transcriptErrorText(phase.version?.errorCode ?? null, msg, about)}\n </Notice>\n );\n }\n return null;\n}\n\nfunction versionLine(\n version: RecordingTranscriptVersion,\n modelName: (version: RecordingTranscriptVersion) => string,\n msg: OpenGeniText = defaultText,\n): string {\n const parts = [\n msg(\"meetings.detailPage.versionVersionnumber\", { versionNumber: version.versionNumber }),\n modelName(version),\n ];\n if (version.state === \"queued\" || version.state === \"processing\")\n parts.push(msg(\"meetings.detailPage.transcribing\"));\n if (version.state === \"failed\") parts.push(msg(\"meetings.detailPage.failed\"));\n if (version.state === \"complete\" && version.languages.length > 0) {\n parts.push(version.languages.map((code) => languageName(code, msg.locale)).join(\", \"));\n }\n return parts.join(\" · \");\n}\n\n/**\n * A newer version than the one shown: still running, or failed. The current\n * transcript stays readable either way, so this is a quiet line, not a block.\n */\nfunction RerunNotice({\n versions,\n shownVersionNumber,\n modelName,\n modelOf,\n fixes,\n onRetry,\n}: {\n versions: readonly RecordingTranscriptVersion[];\n shownVersionNumber: number;\n modelName: (version: RecordingTranscriptVersion) => string;\n modelOf: (version: RecordingTranscriptVersion) => ModelAbout | null;\n fixes: TranscriptFixes;\n onRetry: () => void;\n}) {\n const msg = useOpenGeniText();\n const newest = versions.reduce<RecordingTranscriptVersion | null>(\n (best, entry) => (!best || entry.versionNumber > best.versionNumber ? entry : best),\n null,\n );\n if (!newest || newest.versionNumber <= shownVersionNumber) return null;\n if (newest.state === \"queued\" || newest.state === \"processing\") {\n return (\n <Notice tone=\"waiting\" icon={SPINNER} live=\"polite\">\n {msg(\"meetings.detailPage.transcribingAgainWithModelnameThis\", {\n modelName: modelName(newest),\n })}\n </Notice>\n );\n }\n if (newest.state === \"failed\") {\n return (\n <Notice\n tone=\"failed\"\n title={msg(\"meetings.detailPage.transcribingAgainFailed\")}\n actionLayout=\"responsive\"\n action={\n <FailedTranscriptActions\n version={newest}\n about={modelOf(newest)}\n fixes={fixes}\n onRetry={onRetry}\n />\n }\n >\n {msg(\"meetings.detailPage.transcripterrortextThisVersionIsUnchanged\", {\n transcriptErrorText: transcriptErrorText(newest.errorCode, msg, modelOf(newest)),\n })}\n </Notice>\n );\n }\n return null;\n}\n\n/** The meeting page's tabs. */\ntype MeetingTab = \"summary\" | \"transcript\" | \"notepad\";\n\n/** Summary when there are written notes to read, else Transcript. */\nexport function openingMeetingTab(notes: RecordingNote | null): MeetingTab {\n return notes?.body.trim() ? \"summary\" : \"transcript\";\n}\n\n/** One of the host's own lines about a meeting, such as its project. */\nexport type MeetingDetail = { id: string; label: string; content: ReactNode };\n\ntype MeetingDetailPageProps = {\n workspaceId: string;\n recordingId: string;\n viewerSubjectId: string;\n /** The reader's name, for the people list when they name a speaker as themselves. */\n viewerName?: string;\n /** The workspace recognizes people by voice, so speakers can be suggested and voices remembered. */\n voiceRecognition?: boolean;\n /** A recordings client to use instead of the app's, for previews. */\n recordings?: RecordingsClientOverride[\"recordings\"];\n onBack: () => void;\n /** Opens Meetings settings, where voice recognition is turned on. */\n onOpenSettings?: (() => void) | undefined;\n /**\n * Opens where this person adds credits, the fix a transcript refused for\n * credits offers when no other model works here. Omit it for someone who\n * can't buy credits.\n */\n onOpenBilling?: (() => void) | undefined;\n /**\n * Opens where models are connected, the fix for a transcript whose\n * provider isn't connected. Omit it for someone who can't connect one.\n */\n onConnectModels?: (() => void) | undefined;\n /**\n * The host's own lines about this meeting, shown first beside the\n * transcript, such as the project it belongs to.\n */\n details?: ((recording: Recording) => readonly MeetingDetail[]) | undefined;\n /**\n * The viewer's workspaces in this organization, their Personal workspace\n * marked, so they can choose where their own Only me meetings work\n * (\"Available in\"). Without it the page doesn't offer that choice.\n */\n reachWorkspaces?: readonly ReachWorkspace[] | undefined;\n /** The organization's name, for \"Available in\". */\n organizationName?: string | undefined;\n /** Opens a chat, such as the one whose agent wrote the notes. */\n onOpenChat?: ((sessionId: string) => void) | undefined;\n /**\n * Answers \"Ask about this meeting\", usually by starting a chat with the\n * meeting attached and the question as its first message. Without it the\n * page has no Ask input. Resolve false to keep the question in the input\n * when the host couldn't take it and has already said why.\n */\n onAsk?:\n | ((recordingId: string, question: string) => MeetingAskResult | Promise<MeetingAskResult>)\n | undefined;\n};\n\n/**\n * Each meeting starts fresh, even when the host keeps the page mounted and\n * only changes `recordingId`: its own opening tab, drafts and dialogs.\n */\nexport function MeetingDetailPage(props: MeetingDetailPageProps) {\n return (\n <MeetingsOverlayScope>\n <MeetingDetailPageForRecording key={props.recordingId} {...props} />\n </MeetingsOverlayScope>\n );\n}\n\nfunction MeetingDetailPageForRecording({\n workspaceId,\n recordingId,\n viewerSubjectId,\n viewerName,\n voiceRecognition = false,\n recordings: recordingsClient,\n onBack,\n onOpenSettings,\n onOpenBilling,\n onConnectModels,\n details,\n reachWorkspaces,\n organizationName,\n onOpenChat,\n onAsk,\n}: MeetingDetailPageProps) {\n const msg = useOpenGeniText();\n const override = { workspaceId, ...(recordingsClient ? { recordings: recordingsClient } : {}) };\n const meeting = useRecording(recordingId, override);\n const recording = meeting.recording;\n const version = recording?.transcript ?? null;\n const transcriptVersionId =\n version?.state === \"complete\"\n ? version.id\n : meeting.versions.find((candidate) => candidate.isCurrent && candidate.state === \"complete\")\n ?.id;\n const transcript = useTranscript(recordingId, {\n ...override,\n ...(transcriptVersionId ? { versionId: transcriptVersionId } : {}),\n refreshKey: transcriptVersionId ?? null,\n enabled: Boolean(transcriptVersionId),\n });\n // A person's own Only me meeting from another workspace of the organization\n // keeps its people and transcribers in the workspace that stores it.\n const home = { ...override, workspaceId: recording?.workspaceId ?? workspaceId };\n const people = useRecordingPeople(home);\n const models = useRecordingModels(home);\n const { client } = useRecordingsClient(override);\n const { recorder } = useMeetingRecorder();\n const online = useOnline();\n // The live preview, while a meeting is recorded and until its transcript is\n // ready: this browser's own recorder has it first; anyone else reads what\n // the recorder saved.\n const recordingHere = Boolean(recorder && recorder.recordingId === recordingId && recorder.live);\n const previewing =\n Boolean(recording?.tracks.some((track) => track.live)) &&\n !transcriptVersionId &&\n (recording?.state === \"capturing\" || recording?.state === \"processing\");\n const savedLive = useLiveTranscript(recordingId, {\n ...override,\n enabled: previewing && !recordingHere,\n });\n const player = useRef<MeetingPlayerHandle>(null);\n // The player's bar pins to the top while the page scrolls; pinned, it covers\n // the host scroller's top padding too (sticky-bar-edge.tsx).\n const [playerBar, setPlayerBar] = useState<HTMLDivElement | null>(null);\n const playerPinned = useStuckToTop(playerBar);\n const [position, setPosition] = useState(0);\n const [renaming, setRenaming] = useState(false);\n const [choosingReach, setChoosingReach] = useState(false);\n const [rerunning, setRerunning] = useState(false);\n const [deleting, setDeleting] = useState(false);\n const [namingFromAside, setNamingFromAside] = useState<string | null>(null);\n const [rememberingVoice, setRememberingVoice] = useState<RecordingPerson | null>(null);\n const notes = useRecordingNotes(recordingId, override);\n // The notes name a meeting nobody named: show that name once they arrive.\n // The name is written just after the notes, so it is read again shortly.\n const notesRevision = notes.notes?.revision ?? 0;\n const refreshMeeting = meeting.refresh;\n const awaitingName = Boolean(recording && recording.titleSource !== \"person\");\n const seenNotesRevision = useRef<number | null>(null);\n useEffect(() => {\n if (notes.loading) return;\n const seen = seenNotesRevision.current;\n seenNotesRevision.current = notesRevision;\n if (seen === null || seen === notesRevision || !awaitingName) return;\n void refreshMeeting();\n const again = window.setTimeout(() => void refreshMeeting(), 3_000);\n return () => window.clearTimeout(again);\n }, [notes.loading, notesRevision, awaitingName, refreshMeeting]);\n // Summary when the meeting has written notes, else Transcript: decided once\n // the notes load, so notes written later don't move the reader.\n const [openingTab, setOpeningTab] = useState<MeetingTab | null>(null);\n const [chosenTab, setChosenTab] = useState<MeetingTab | null>(null);\n if (openingTab === null && !notes.loading) {\n setOpeningTab(openingMeetingTab(notes.notes));\n }\n const tab = chosenTab ?? openingTab;\n // The ⌘K menu's \"Ask about this meeting\": the Ask field shows on Summary and\n // Transcript, so a question from the Notepad tab moves to Summary first.\n const [askRequest, setAskRequest] = useState<MeetingAskRequest | null>(null);\n const tabRef = useRef(tab);\n tabRef.current = tab;\n const askFromMenu = useCallback((question: string | null) => {\n if (tabRef.current === \"notepad\") setChosenTab(\"summary\");\n setAskRequest((current) => ({ question, nonce: (current?.nonce ?? 0) + 1 }));\n }, []);\n const recordingOnScreenHere =\n recording?.state === \"capturing\" &&\n [\"recording\", \"paused\"].includes(meetingHereStatus(recorder, recordingId, online) ?? \"\");\n useAnnounceMeetingOnScreen(\n useUiEventTarget(\"document\"),\n recordingId,\n onAsk && recording && !recordingOnScreenHere ? askFromMenu : null,\n );\n const slots = useMemo(() => speakerColorSlots(transcript.segments), [transcript.segments]);\n const mentionTracks = recording?.tracks;\n const mentions = useMemo(\n () =>\n meetingMentionResolver({\n speakers: transcript.speakers,\n tracks: mentionTracks ?? [],\n people: people.people,\n slots,\n msg,\n }),\n [transcript.speakers, mentionTracks, people.people, slots, msg],\n );\n\n const { sources, reload } = useTrackSources(recording, (trackNumber) =>\n client.getRecordingTrackAudio(workspaceId, recordingId, trackNumber),\n );\n\n const modelName = useCallback(\n (entry: RecordingTranscriptVersion) =>\n models.models.find(\n (candidate) => candidate.providerId === entry.providerId && candidate.model === entry.model,\n )?.name ?? entry.model,\n [models.models],\n );\n const modelOf = useCallback(\n (entry: RecordingTranscriptVersion): ModelAbout | null => {\n const found = models.models.find(\n (candidate) => candidate.providerId === entry.providerId && candidate.model === entry.model,\n );\n return found\n ? {\n modelName: found.name,\n providerName: found.providerName,\n funding: found.funding,\n pinned: models.pinned,\n }\n : null;\n },\n [models.models, models.pinned],\n );\n // A failed transcript's direct fix runs another model with this meeting's\n // own options; null language detects it, as Transcribe again does.\n const rerunMeeting = meeting.rerun;\n const shownTranscription = recording?.transcription;\n const fixes: TranscriptFixes = {\n models: models.models,\n onTranscribeWith: async (model) => {\n const { providerId: _provider, model: _model, ...options } = shownTranscription ?? {};\n await rerunMeeting({\n ...options,\n providerId: model.providerId,\n model: model.model,\n language: options.language ?? null,\n });\n },\n onOpenBilling,\n onConnectModels,\n };\n\n const createPerson = people.create;\n const { rememberVoice, forgetVoice } = people;\n const refreshTranscript = transcript.refresh;\n const rejectSuggestion = transcript.rejectSuggestion;\n const nameSpeaker = transcript.nameSpeaker;\n const transcriptSpeakers = transcript.speakers;\n const peopleList = people.people;\n // Naming reads the people list right after a person was created, before\n // the list has rerendered with them.\n const latestPeople = useRef(peopleList);\n latestPeople.current = peopleList;\n const createdPeople = useRef(new Map<string, RecordingPerson>());\n const offeredVoices = useRef(new Set<string>());\n // Without voice recognition a name is only for this meeting; say so once,\n // the first time someone is named here.\n const toldNotRemembered = useRef(false);\n const tellNotRemembered = useCallback(() => {\n if (voiceRecognition || toldNotRemembered.current) return;\n toldNotRemembered.current = true;\n toast(msg(\"meetings.detailPage.namesArenTSuggestedIn\"), {\n description: msg(\"meetings.detailPage.voiceRecognitionIsOffIn\"),\n ...(onOpenSettings\n ? { action: { label: msg(\"meetings.detailPage.settings\"), onClick: onOpenSettings } }\n : {}),\n });\n }, [msg, voiceRecognition, onOpenSettings]);\n const offerMyVoice = useCallback(\n (me: RecordingPerson) => {\n // Naming yourself is when remembering your voice makes sense.\n toast.success(msg(\"meetings.detailPage.namedYou\"), {\n // Long enough to read and decide; the speaker menu offers it later too.\n duration: 10_000,\n description: msg(\"meetings.detailPage.rememberYourVoiceAndLater\"),\n action: {\n label: msg(\"meetings.detailPage.rememberMyVoice\"),\n onClick: () =>\n void rememberVoice(me.id, \"self\").then(\n () => toast.success(msg(\"meetings.detailPage.yourVoiceWillBeRemembered\")),\n (error: unknown) =>\n toast.error(msg(\"meetings.detailPage.couldnTRememberYourVoice\"), {\n description: errorText(error),\n }),\n ),\n },\n });\n },\n [msg, rememberVoice],\n );\n // A name teaches nothing until the person's voice may be remembered, so\n // say so once per person, the first time they're named here. Another\n // member decides for themselves, so naming them offers nothing.\n const offerToRemember = useCallback(\n (personId: string) => {\n const person =\n latestPeople.current.find((candidate) => candidate.id === personId) ??\n createdPeople.current.get(personId);\n if (!person || person.voice || offeredVoices.current.has(person.id)) return;\n const self = Boolean(viewerSubjectId) && person.memberSubjectId === viewerSubjectId;\n if (person.memberSubjectId && !self) return;\n offeredVoices.current.add(person.id);\n if (self) {\n offerMyVoice(person);\n return;\n }\n toast.success(\n msg(\"meetings.detailPage.namedDisplayname\", { displayName: person.displayName }),\n {\n duration: 10_000,\n description: msg(\"meetings.detailPage.rememberTheirVoiceAndLater\"),\n action: {\n label: msg(\"meetings.detailPage.rememberVoice\"),\n onClick: () => setRememberingVoice(person),\n },\n },\n );\n },\n [msg, viewerSubjectId, offerMyVoice],\n );\n const actions: TranscriptActions = useMemo(\n () => ({\n nameSpeaker: async (label, name) => {\n await nameSpeaker(label, name);\n if (!name) return;\n if (!voiceRecognition) tellNotRemembered();\n else if (\"personId\" in name) offerToRemember(name.personId);\n },\n viewerSubjectId,\n nameSelf: async (label: string) => {\n const me =\n peopleList.find((person) => person.memberSubjectId === viewerSubjectId) ??\n (await createPerson({\n displayName: viewerName ?? msg(\"meetings.detailPage.me\"),\n memberSubjectId: viewerSubjectId,\n }));\n await nameSpeaker(label, { personId: me.id });\n if (!voiceRecognition) {\n tellNotRemembered();\n } else if (!me.voice) {\n offeredVoices.current.add(me.id);\n offerMyVoice(me);\n }\n },\n rejectSuggestion: async (label: string) => {\n const suggested = speakerIsSuggested(label, transcriptSpeakers);\n await rejectSuggestion(label);\n const personId = suggested?.personId;\n toast.success(\n suggested\n ? msg(\"meetings.detailPage.suggestionDismissed\")\n : msg(\"meetings.detailPage.leftUnnamed\"),\n suggested && personId\n ? {\n description: msg(\"meetings.detailPage.thisSpeakerIsUnnamedAgain\"),\n // A mis-tap on \"Not them\" is easy; naming them puts it right.\n action: {\n label: msg(\"meetings.detailPage.undo\"),\n onClick: () =>\n void nameSpeaker(label, { personId }).catch((error: unknown) =>\n toast.error(msg(\"meetings.detailPage.couldnTNameThisSpeaker\"), {\n description: errorText(error),\n }),\n ),\n },\n }\n : undefined,\n );\n },\n moveSegment: transcript.moveSegment,\n editSegment: transcript.editSegment,\n createPerson: async (displayName: string) => {\n const person = await createPerson({ displayName });\n createdPeople.current.set(person.id, person);\n return person;\n },\n voices: voiceRecognition\n ? {\n viewerSubjectId,\n remember: (person) => {\n if (person.memberSubjectId !== viewerSubjectId) {\n setRememberingVoice(person);\n return;\n }\n void rememberVoice(person.id, \"self\").then(\n () => toast.success(msg(\"meetings.detailPage.yourVoiceWillBeRemembered\")),\n (error: unknown) =>\n toast.error(msg(\"meetings.detailPage.couldnTRememberYourVoice\"), {\n description: errorText(error),\n }),\n );\n },\n forget: async (person) => {\n await forgetVoice(person.id);\n // Forgetting also removes the names it suggested in this meeting.\n await refreshTranscript();\n toast.success(\n person.memberSubjectId === viewerSubjectId\n ? msg(\"meetings.detailPage.yourVoiceIsForgotten\")\n : msg(\"meetings.detailPage.displaynameSVoiceIsForgotten\", {\n displayName: person.displayName,\n }),\n );\n },\n }\n : null,\n }),\n [\n msg,\n nameSpeaker,\n rejectSuggestion,\n transcriptSpeakers,\n transcript.moveSegment,\n transcript.editSegment,\n createPerson,\n voiceRecognition,\n viewerSubjectId,\n viewerName,\n peopleList,\n tellNotRemembered,\n offerMyVoice,\n offerToRemember,\n rememberVoice,\n forgetVoice,\n refreshTranscript,\n ],\n );\n\n if (!recording) {\n return (\n <DetailPage back={{ label: msg(\"meetings.detailPage.meetings\"), onClick: onBack }}>\n {meeting.error ? (\n isNotFound(meeting.error) ? (\n <EmptyState\n variant=\"page\"\n icon={<AudioLinesIcon />}\n title={msg(\"meetings.detailPage.thisMeetingDoesnTExist\")}\n description={msg(\"meetings.detailPage.itMayHaveBeenDeleted\")}\n action={\n <Button type=\"button\" variant=\"outline\" onClick={onBack}>\n {msg(\"meetings.detailPage.backToMeetings\")}\n </Button>\n }\n className=\"pt-12\"\n />\n ) : (\n <ErrorMessage\n align=\"center\"\n title={msg(\"meetings.detailPage.couldnTLoadThisMeeting\")}\n details={[{ label: msg(\"meetings.detailPage.error\"), value: meeting.error.message }]}\n action={\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void meeting.refresh()}\n >\n {msg(\"meetings.detailPage.tryAgain\")}\n </Button>\n }\n >\n {msg(\"meetings.detailPage.checkYourConnectionThenTry\")}\n </ErrorMessage>\n )\n ) : (\n <div aria-busy=\"true\" className=\"grid gap-6\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-7 w-72\" />\n <Skeleton className=\"h-4 w-96 max-w-full\" />\n </div>\n <Skeleton className=\"h-12 w-full rounded-[14px]\" />\n <div className=\"space-y-3\">\n <Skeleton className=\"h-4 w-40\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-5/6\" />\n </div>\n <span className=\"sr-only\" role=\"status\">\n {msg(\"meetings.detailPage.loadingMeeting\")}\n </span>\n </div>\n )}\n </DetailPage>\n );\n }\n\n const owner = recording.ownerSubjectId === viewerSubjectId;\n // The owner's own Only me meeting, on a server that keeps where it works.\n const reachable =\n owner &&\n recording.visibility === \"private\" &&\n recording.purpose === \"meeting\" &&\n recording.reachWorkspaceIds !== undefined &&\n reachWorkspaces !== undefined;\n // The person recording, as the transcript will name their microphone.\n const ownerName =\n peopleList.find((person) => person.memberSubjectId === recording.ownerSubjectId)?.displayName ??\n (owner ? (viewerName ?? null) : null);\n const phase = meetingPhase(recording);\n // Only while the server still waits for audio: this device may know more.\n const here =\n recording.state === \"capturing\" ? meetingHereStatus(recorder, recording.id, online) : null;\n const capturingHere = here === \"recording\" || here === \"paused\";\n // Recording on this device: one page with the bar, the notepad and the live\n // preview. Once it stops (and everywhere else), Summary · Transcript · Notepad,\n // with this recorder's live text in Transcript until the transcript is ready.\n const tabbed = !capturingHere;\n const askable = Boolean(onAsk);\n const segments = transcript.segments;\n const speakerLabels = [...slots.keys()];\n const activeSegment = sources.length > 0 ? activeSegmentIndex(segments, position) : null;\n const showTranscript = Boolean(transcriptVersionId);\n const shownVersionNumber = version?.state === \"complete\" ? version.versionNumber : 0;\n const rerunPending = meeting.versions.some(\n (entry) =>\n entry.versionNumber > shownVersionNumber &&\n (entry.state === \"queued\" || entry.state === \"processing\"),\n );\n // Gone once retention deleted it, or when none was ever uploaded. Uploaded\n // audio without a playable copy yet (while it's transcribed, or after a\n // failure before that step) can still be transcribed again.\n const audioGone =\n recording.audioDeletedAt !== null ||\n (recording.state !== \"capturing\" &&\n !recording.tracks.some((track) => track.playable || track.chunkCount > 0));\n const canRerun = recording.state !== \"capturing\" && !audioGone && !rerunPending;\n // Pending before any transcript is done, it is the first one, not \"again\".\n const firstPending = rerunPending && shownVersionNumber === 0;\n const unnamedCount = speakerLabels.filter(\n (label) => !speakerIsNamed(label, transcript.speakers),\n ).length;\n const suggestedCount = speakerLabels.filter((label) =>\n speakerIsSuggested(label, transcript.speakers),\n ).length;\n // Speakers that still need someone to say who they are: unnamed, or a\n // name suggested from a voice that nobody has confirmed yet.\n const reviewLabels = speakerLabels.filter(\n (label) =>\n !speakerIsNamed(label, transcript.speakers) ||\n Boolean(speakerIsSuggested(label, transcript.speakers)),\n );\n\n const speakerButtons = (variant: \"list\" | \"chips\", labels: readonly string[] = speakerLabels) =>\n labels.map((label) => {\n const name = speakerDisplayName(label, transcript.speakers, recording.tracks, msg);\n const suggested = speakerIsSuggested(label, transcript.speakers);\n const unnamed = !speakerIsNamed(label, transcript.speakers);\n const menuLabel = suggested\n ? msg(\"meetings.detailPage.nameSuggestedFromTheirVoice\", { name: name })\n : unnamed\n ? msg(\"meetings.detailPage.nameNameThisSpeaker\", { name: name })\n : msg(\"meetings.detailPage.nameChangeWhoThisIs\", { name: name });\n return (\n <li key={label} className=\"min-w-0\">\n <SpeakerNameMenu\n label={label}\n displayName={name}\n speakers={transcript.speakers}\n people={people.people}\n actions={actions}\n onAddNew={setNamingFromAside}\n align={variant === \"list\" ? \"end\" : \"start\"}\n >\n {variant === \"list\" ? (\n <button\n type=\"button\"\n aria-label={menuLabel}\n className=\"-mx-1.5 flex w-[calc(100%+0.75rem)] min-w-0 items-center gap-2 rounded-[6px] px-1.5 py-1 text-left text-sm leading-5 text-fg transition-colors duration-[120ms] hover:bg-hover data-[state=open]:bg-hover pointer-coarse:min-h-11\"\n >\n <SpeakerDot slot={slots.get(label)} />\n <span className=\"grid min-w-0 flex-1\">\n <span className=\"truncate\">{name}</span>\n {suggested ? (\n <span className=\"truncate text-xs leading-4 text-fg-muted\">\n {msg(\"meetings.detailPage.suggestedFromTheirVoice\")}\n </span>\n ) : null}\n </span>\n <PencilIcon aria-hidden=\"true\" className=\"size-3.5 shrink-0 text-fg-subtle\" />\n </button>\n ) : (\n <button\n type=\"button\"\n aria-label={menuLabel}\n className={cn(\n \"flex max-w-52 min-w-0 items-center gap-2 rounded-full border border-border bg-surface px-3 py-1 text-sm leading-5 text-fg transition-colors duration-[120ms] hover:bg-hover data-[state=open]:bg-hover pointer-coarse:min-h-11\",\n (suggested || unnamed) && \"border-dashed border-border-strong\",\n )}\n >\n <SpeakerDot slot={slots.get(label)} />\n <span className=\"min-w-0 truncate\">\n {name}\n {suggested ? \"?\" : \"\"}\n </span>\n <PencilIcon aria-hidden=\"true\" className=\"size-3 shrink-0 text-fg-subtle\" />\n </button>\n )}\n </SpeakerNameMenu>\n {suggested && variant === \"list\" ? (\n <div className=\"mt-1 flex flex-wrap gap-1.5 pl-4\">\n <Button\n type=\"button\"\n size=\"xs\"\n className=\"pointer-coarse:h-11\"\n variant=\"outline\"\n aria-label={msg(\"meetings.detailPage.yesItSName\", { name: name })}\n onClick={() =>\n void actions\n .nameSpeaker(label, { personId: suggested.personId! })\n .catch((error: unknown) =>\n toast.error(msg(\"meetings.detailPage.couldnTConfirmThisName\"), {\n description: errorText(error),\n }),\n )\n }\n >\n <CheckIcon aria-hidden=\"true\" />\n {msg(\"meetings.detailPage.confirm\")}\n </Button>\n <Button\n type=\"button\"\n size=\"xs\"\n className=\"pointer-coarse:h-11\"\n variant=\"ghost\"\n aria-label={msg(\"meetings.detailPage.notName\", { name: name })}\n onClick={() =>\n void actions.rejectSuggestion(label).catch((error: unknown) =>\n toast.error(msg(\"meetings.detailPage.couldnTTurnDownThis\"), {\n description: errorText(error),\n }),\n )\n }\n >\n {msg(\"meetings.detailPage.notThem\")}\n </Button>\n </div>\n ) : null}\n </li>\n );\n });\n const reviewLine =\n reviewLabels.length === 0\n ? null\n : unnamedCount > 0 && suggestedCount > 0\n ? suggestedCount === 1\n ? msg(\"meetings.detailPage.whoSpokeSpeakersToNameOneName\", {\n count: unnamedCount,\n suggestedCount: suggestedCount,\n })\n : msg(\"meetings.detailPage.whoSpokeSpeakersToNameNames\", {\n count: unnamedCount,\n suggestedCount: suggestedCount,\n })\n : unnamedCount > 0\n ? msg(\"meetings.detailPage.whoSpokeSpeakersHaveNoName\", { count: unnamedCount })\n : msg(\"meetings.detailPage.whoSpokeNamesWereSuggested\", { count: suggestedCount });\n\n const update = async (\n request: Parameters<typeof meeting.update>[0],\n failure: string,\n ): Promise<void> => {\n try {\n await meeting.update(request);\n } catch (error) {\n toast.error(failure, { description: errorText(error) });\n throw error;\n }\n };\n\n const shownTitle = meetingTitle(recording, msg);\n const header = (\n <DetailPageHeader\n title={shownTitle}\n tabs={\n !tabbed ? undefined : tab === null ? (\n <Skeleton className=\"h-9 w-64 rounded-[10px]\" />\n ) : (\n <SegmentedControl\n aria-label={msg(\"meetings.detailPage.show\")}\n value={tab}\n onValueChange={setChosenTab}\n options={[\n { value: \"summary\", label: msg(\"meetings.detailPage.summary\") },\n { value: \"transcript\", label: msg(\"meetings.detailPage.transcript\") },\n { value: \"notepad\", label: msg(\"meetings.notes.notepad\") },\n ]}\n />\n )\n }\n meta={\n <DetailMeta>\n {formatAbsoluteTime(recording.startedAt, { text: msg })}\n {recording.durationMilliseconds > 0\n ? formatDuration(recording.durationMilliseconds, msg)\n : null}\n {speakerLabels.length > 0\n ? msg(\"meetings.detailPage.countSpeakers\", { count: speakerLabels.length })\n : null}\n {!owner && recording.visibility === \"workspace\"\n ? msg(\"meetings.detailPage.sharedWithTheWorkspace\")\n : null}\n {recording.sourceWorkspace\n ? msg(\"meetings.detailPage.onlyMeRecordedIn\", {\n workspace: recording.sourceWorkspace.name,\n })\n : null}\n </DetailMeta>\n }\n actions={\n <>\n {owner && !recording.sourceWorkspace ? (\n <VisibilityMenu\n visibility={recording.visibility}\n onChange={(visibility) =>\n void update({ visibility }, msg(\"meetings.detailPage.couldnTChangeWhoCan\")).then(\n () =>\n toast.success(\n visibility === \"workspace\"\n ? msg(\"meetings.detailPage.sharedWithTheWorkspace\")\n : msg(\"meetings.detailPage.onlyYouCanSeeThis\"),\n ),\n () => undefined,\n )\n }\n />\n ) : null}\n <MoreMenu label={msg(\"meetings.detailPage.moreActionsForTitle\", { title: shownTitle })}>\n <DropdownMenuItem onSelect={() => setRenaming(true)}>\n <PencilIcon aria-hidden=\"true\" />\n {msg(\"meetings.detailPage.rename\")}\n </DropdownMenuItem>\n {reachable ? (\n <DropdownMenuItem onSelect={() => setChoosingReach(true)}>\n <LayersIcon aria-hidden=\"true\" />\n {msg(\"meetings.detailPage.availableInMenu\")}\n </DropdownMenuItem>\n ) : null}\n {recording.state !== \"capturing\" ? (\n <DropdownMenuItem disabled={!canRerun} onSelect={() => setRerunning(true)}>\n <RefreshCwIcon aria-hidden=\"true\" />\n {rerunPending && !firstPending\n ? msg(\"meetings.detailPage.transcribingAgain\")\n : msg(\"meetings.detailPage.transcribeAgain\")}\n </DropdownMenuItem>\n ) : null}\n {owner ? (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem variant=\"destructive\" onSelect={() => setDeleting(true)}>\n <Trash2Icon aria-hidden=\"true\" />\n {msg(\"meetings.detailPage.deleteMeeting\")}\n </DropdownMenuItem>\n </>\n ) : null}\n </MoreMenu>\n </>\n }\n />\n );\n\n const hostDetails = details?.(recording) ?? [];\n const aside =\n showTranscript || meeting.versions.length > 0 || hostDetails.length > 0 ? (\n <DetailAside label={msg(\"meetings.detailPage.aboutThisTranscript\")}>\n {hostDetails.map((detail) => (\n <DetailAsideItem key={detail.id} label={detail.label}>\n {detail.content}\n </DetailAsideItem>\n ))}\n {speakerLabels.length > 0 ? (\n <DetailAsideItem label={msg(\"meetings.detailPage.speakers\")}>\n <div className=\"grid w-full min-w-0 gap-1\">\n <ul className=\"grid w-full min-w-0 gap-1\">{speakerButtons(\"list\")}</ul>\n {canRerun ? (\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"xs\"\n onClick={() => setRerunning(true)}\n className=\"h-auto w-fit px-0 text-fg-muted pointer-coarse:h-11\"\n >\n {msg(\"meetings.detailPage.wrongNumberOfSpeakers\")}\n </Button>\n ) : null}\n </div>\n </DetailAsideItem>\n ) : null}\n {meeting.versions.length > 0 ? (\n <DetailAsideItem label={msg(\"meetings.detailPage.transcript\")}>\n <div className=\"grid w-full min-w-0 gap-2\">\n {meeting.versions.length > 1 ? (\n <NativeSelect\n options={meeting.versions.map((entry) => ({\n value: entry.id,\n label: versionLine(entry, modelName, msg),\n disabled: entry.state !== \"complete\",\n }))}\n value={transcriptVersionId ?? meeting.versions[0]!.id}\n onValueChange={(versionId) =>\n void meeting.setCurrentVersion(versionId).catch((error: unknown) =>\n toast.error(msg(\"meetings.detailPage.couldnTSwitchVersions\"), {\n description: errorText(error),\n }),\n )\n }\n size=\"sm\"\n />\n ) : (\n <span className=\"text-sm leading-5 text-fg\">\n {versionLine(meeting.versions[0]!, modelName, msg)}\n </span>\n )}\n {phase.kind === \"failed\" || firstPending ? null : (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setRerunning(true)}\n disabled={!canRerun}\n className=\"w-fit rounded-[10px] pointer-coarse:h-11\"\n >\n {rerunPending ? SPINNER : <RefreshCwIcon aria-hidden=\"true\" />}\n {rerunPending\n ? msg(\"meetings.detailPage.transcribingAgain\")\n : msg(\"meetings.detailPage.transcribeAgain\")}\n </Button>\n )}\n </div>\n </DetailAsideItem>\n ) : null}\n </DetailAside>\n ) : undefined;\n\n // What the Transcript shows: who still needs a name, then the transcript,\n // or why there isn't one yet.\n const transcriptBody = (\n <>\n {showTranscript && reviewLabels.length > 0 ? (\n // Beside the speakers card, the speakers still to review sit at\n // the top of the transcript, where the reader starts. Only the outer\n // wrapper hides, so no display class competes with the container query.\n <div className=\"mb-5 @max-[620px]/detail:hidden\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"text-sm leading-5 text-fg-muted\">{reviewLine}</p>\n <ul\n aria-label={msg(\"meetings.detailPage.speakersToReview\")}\n className=\"flex flex-wrap gap-2\"\n >\n {speakerButtons(\"chips\", reviewLabels)}\n </ul>\n </div>\n </div>\n ) : null}\n {showTranscript && speakerLabels.length > 0 ? (\n // Only while the speakers card sits below the transcript. The\n // wrapper carries no display class, so the container query wins.\n <div className=\"mb-5 @[620px]/detail:hidden\">\n <div className=\"grid gap-2\">\n <ul aria-label={msg(\"meetings.detailPage.speakers\")} className=\"flex flex-wrap gap-2\">\n {speakerButtons(\"chips\")}\n </ul>\n {reviewLine ? (\n <p className=\"text-xs leading-4.5 text-fg-muted\">\n {msg(\"meetings.detailPage.reviewlineTapADashedName\", {\n reviewLine: reviewLine,\n })}\n </p>\n ) : null}\n </div>\n </div>\n ) : null}\n {!showTranscript && (previewing || recordingHere) ? (\n <div className=\"grid gap-3\">\n <p className=\"text-sm leading-5 text-fg-muted\">\n <span className=\"mr-2 inline-flex rounded-full border border-border px-1.5 text-xs leading-4 font-medium text-fg-label\">\n {msg(\"meetings.detailPage.preview\")}\n </span>\n {recording.state === \"capturing\" && here !== \"transcribing\"\n ? msg(\"meetings.detailPage.whatSSaidSoFar\")\n : msg(\"meetings.detailPage.whatWasSaidAsIt\")}\n </p>\n {recordingHere && recorder?.live ? (\n <LiveTranscript\n heading={false}\n lines={recorderLiveLines(recorder)}\n partials={recorder.live.map((track) => ({\n trackNumber: track.trackNumber,\n text: track.partial,\n }))}\n tracks={recorder.tracks}\n speakerName={(trackNumber) => liveSpeakerName(recorder, trackNumber, msg, ownerName)}\n status={liveStatus(recorder.live, msg)}\n empty={msg(\"meetings.detailPage.listeningWhatSSaidShows\")}\n />\n ) : (\n <LiveTranscript\n heading={false}\n lines={savedLive.segments}\n tracks={recording.tracks}\n speakerName={(trackNumber) => {\n const source = defaultSpeakerName(`track-${trackNumber}`, recording.tracks, msg);\n return (\n ownerLiveLaneName(recording.tracks, trackNumber, ownerName ?? source, msg) ??\n source\n );\n }}\n status={\n savedLive.error\n ? { text: msg(\"meetings.detailPage.canTLoadThePreview\"), tone: \"waiting\" }\n : null\n }\n empty={\n recording.state === \"capturing\"\n ? msg(\"meetings.detailPage.nothingSaidYetTextShows\")\n : msg(\"meetings.detailPage.noLiveTextWasSaved\")\n }\n />\n )}\n </div>\n ) : !showTranscript ? (\n <p className=\"text-sm leading-5 text-fg-muted\">\n {phase.kind === \"failed\"\n ? msg(\"meetings.detailPage.noTranscriptYet\")\n : phase.kind === \"no_transcript\"\n ? msg(\"meetings.detailPage.thisMeetingHasnTBeen\")\n : msg(\"meetings.detailPage.theTranscriptShowsHereWhen\")}\n </p>\n ) : transcript.loading && segments.length === 0 ? (\n <div className=\"space-y-3\" aria-busy=\"true\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-4/5\" />\n </div>\n ) : transcript.error && segments.length === 0 ? (\n <ErrorMessage\n title={msg(\"meetings.detailPage.couldnTLoadTheTranscript\")}\n details={[{ label: msg(\"meetings.detailPage.error\"), value: transcript.error.message }]}\n action={\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void transcript.refresh()}\n >\n {msg(\"meetings.detailPage.tryAgain\")}\n </Button>\n }\n >\n {msg(\"meetings.detailPage.checkYourConnectionThenTry\")}\n </ErrorMessage>\n ) : segments.length === 0 ? (\n <p className=\"text-sm leading-5 text-fg-muted\">\n {msg(\"meetings.detailPage.noSpeechWasFoundIn\")}\n </p>\n ) : (\n <MeetingTranscript\n segments={segments}\n speakers={transcript.speakers}\n tracks={recording.tracks}\n people={people.people}\n activeSegment={activeSegment}\n actions={actions}\n onSeek={sources.length > 0 ? (ms) => player.current?.playFrom(ms) : null}\n />\n )}\n </>\n );\n\n return (\n <DetailPage back={{ label: msg(\"meetings.detailPage.meetings\"), onClick: onBack }}>\n {header}\n <div className=\"mt-6 grid gap-4 empty:hidden\">\n <PhaseNotice\n recording={recording}\n recorder={recorder}\n here={here}\n recordingElsewhere={previewing && !recordingHere}\n modelOf={modelOf}\n fixes={fixes}\n onRetry={() => setRerunning(true)}\n />\n {phase.kind === \"ready\" ? (\n <RerunNotice\n versions={meeting.versions}\n shownVersionNumber={phase.version.versionNumber}\n modelName={modelName}\n modelOf={modelOf}\n fixes={fixes}\n onRetry={() => setRerunning(true)}\n />\n ) : null}\n {audioGone ? (\n <Notice tone=\"muted\">\n {recording.audioDeletedAt\n ? msg(\"meetings.detailPage.theAudioWasDeletedOn\", {\n formatAbsoluteTime: formatAbsoluteTime(recording.audioDeletedAt, { text: msg }),\n })\n : msg(\"meetings.detailPage.theAudioForThisMeeting\")}\n </Notice>\n ) : null}\n </div>\n {sources.length > 0 && !recording.audioDeletedAt ? (\n // A direct child of the page, so it stays in view through the whole transcript.\n <div ref={setPlayerBar} className=\"sticky top-0 z-10 -mx-1 mt-4 bg-bg px-1 pt-2 pb-2\">\n {playerPinned ? <StickyBarEdge edge=\"top\" /> : null}\n <MeetingPlayer\n ref={player}\n sources={sources}\n durationMilliseconds={recording.durationMilliseconds}\n onTime={setPosition}\n onSourceError={reload}\n />\n </div>\n ) : null}\n <DetailPageBody aside={aside}>\n {tabbed ? (\n // One column under the tabs; Ask keeps its draft across Summary and\n // Transcript. The Summary stays mounted while hidden, so an edit in\n // progress survives a look at the transcript.\n <div className=\"flex min-w-0 flex-col\">\n {tab === null ? (\n <DetailSection>\n <div aria-busy=\"true\" className=\"grid gap-3\">\n <Skeleton className=\"h-4 w-2/3\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-1/2\" />\n </div>\n </DetailSection>\n ) : (\n <>\n <div hidden={tab !== \"summary\"} data-meeting-tab=\"summary\">\n <DetailSection className={askable ? \"pb-2\" : undefined}>\n <MeetingSummary notes={notes} onOpenChat={onOpenChat} mentions={mentions} />\n </DetailSection>\n </div>\n {tab === \"transcript\" ? (\n <DetailSection key=\"transcript\" className={askable ? \"pb-2\" : undefined}>\n {transcriptBody}\n </DetailSection>\n ) : tab === \"notepad\" ? (\n <DetailSection key=\"notepad\">\n <MeetingNotepad notes={notes} />\n </DetailSection>\n ) : null}\n </>\n )}\n {askable && onAsk && tab !== \"notepad\" ? (\n <MeetingAsk\n onAsk={(question) => onAsk(recording.id, question)}\n request={askRequest}\n onRequestTaken={() => setAskRequest(null)}\n />\n ) : null}\n </div>\n ) : (\n // Recording here: the notepad first, then the live preview, as one page.\n <>\n <MeetingNotesSection\n notes={notes}\n capturing={recording.state === \"capturing\"}\n onOpenChat={onOpenChat}\n mentions={mentions}\n />\n <DetailSection title={msg(\"meetings.detailPage.transcript\")}>\n {transcriptBody}\n </DetailSection>\n </>\n )}\n </DetailPageBody>\n <RenameDialog\n open={renaming}\n title={shownTitle}\n onClose={() => setRenaming(false)}\n onRename={async (title) =>\n await update({ title }, msg(\"meetings.detailPage.couldnTRenameThisMeeting2\"))\n }\n />\n {reachable ? (\n <MeetingReachDialog\n open={choosingReach}\n recording={recording}\n hereId={workspaceId}\n workspaces={reachWorkspaces ?? []}\n organizationName={organizationName ?? msg(\"meetings.detailPage.thisOrganization\")}\n onClose={() => setChoosingReach(false)}\n onSave={async (reachWorkspaceIds, leavesHere) => {\n if (!leavesHere) {\n await meeting.update({ reachWorkspaceIds });\n return;\n }\n // It no longer works here: save without reading it back, then leave.\n await client.updateRecording(workspaceId, recording.id, { reachWorkspaceIds });\n toast.success(msg(\"meetings.detailPage.itNoLongerShowsHere\"));\n onBack();\n }}\n />\n ) : null}\n <TranscribeAgainDialog\n open={rerunning}\n recording={recording}\n models={models.models}\n defaultModel={models.defaultModel}\n onClose={() => setRerunning(false)}\n onRun={async (options) => {\n await meeting.rerun(options);\n toast.success(msg(\"meetings.detailPage.transcribingAgain2\"), {\n description: msg(\"meetings.detailPage.theNewVersionReplacesThis\"),\n });\n }}\n />\n <NewSpeakerNameDialog\n label={namingFromAside}\n displayName={\n namingFromAside\n ? speakerDisplayName(namingFromAside, transcript.speakers, recording.tracks, msg)\n : \"\"\n }\n actions={actions}\n onClose={() => setNamingFromAside(null)}\n />\n <ConfirmDialog\n open={rememberingVoice !== null}\n onOpenChange={(open) => {\n if (!open) setRememberingVoice(null);\n }}\n destructive={false}\n title={msg(\"meetings.detailPage.rememberValueSVoice\", {\n value: rememberingVoice?.displayName ?? msg(\"meetings.detailPage.their\"),\n })}\n description={msg(\"meetings.detailPage.onlyDoThisIfValue\", {\n value: rememberingVoice?.displayName ?? msg(\"meetings.detailPage.they\"),\n })}\n confirmLabel={msg(\"meetings.detailPage.theyAgreedRemember\")}\n pendingLabel={msg(\"meetings.detailPage.saving\")}\n onConfirm={async () => {\n const person = rememberingVoice;\n if (!person) return;\n try {\n await rememberVoice(person.id, \"attested\");\n toast.success(\n msg(\"meetings.detailPage.displaynameSVoiceWillBe\", {\n displayName: person.displayName,\n }),\n );\n } catch (error) {\n toast.error(msg(\"meetings.detailPage.couldnTRememberThisVoice\"), {\n description: errorText(error),\n });\n return false;\n }\n }}\n />\n <DeleteMeetingDialog\n recording={deleting ? { id: recording.id, title: shownTitle } : null}\n onClose={() => setDeleting(false)}\n onDelete={async () => await meeting.remove()}\n onDeleted={onBack}\n />\n </DetailPage>\n );\n}\n","/**\n * Plays a meeting's tracks together: the microphone and the shared audio are\n * separate files, so one control drives every <audio> element and keeps the\n * followers within a quarter second of the first track.\n */\nimport { useOpenGeniText } from \"../messages/runtime\";\nimport { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from \"react\";\nimport { PauseIcon, PlayIcon, RotateCcwIcon, RotateCwIcon } from \"lucide-react\";\n\nimport { Button } from \"../ui/button\";\nimport { cn } from \"../app/lib/utils\";\n\nimport { formatClock } from \"../recordings\";\n\nexport type MeetingPlayerHandle = {\n /** Jump to a moment and play from there. */\n playFrom: (milliseconds: number) => void;\n};\n\nexport type MeetingPlayerSource = { trackNumber: number; url: string };\n\nconst RATES = [1, 1.25, 1.5, 2] as const;\nconst MAX_DRIFT_SECONDS = 0.25;\nconst SKIP_SECONDS = 15;\n\nexport const MeetingPlayer = forwardRef<\n MeetingPlayerHandle,\n {\n sources: MeetingPlayerSource[];\n /** Known length, shown before the audio's own metadata loads. */\n durationMilliseconds: number;\n /** Called about four times a second while playing, and on every seek. */\n onTime?: ((milliseconds: number) => void) | undefined;\n /** A track's link expired or failed; the parent fetches fresh links. */\n onSourceError?: (() => void) | undefined;\n className?: string | undefined;\n }\n>(function MeetingPlayer({ sources, durationMilliseconds, onTime, onSourceError, className }, ref) {\n const msg = useOpenGeniText();\n const audioRefs = useRef<Map<number, HTMLAudioElement>>(new Map());\n const [playing, setPlaying] = useState(false);\n const [current, setCurrent] = useState(0);\n const [duration, setDuration] = useState(durationMilliseconds / 1000);\n const [rate, setRate] = useState<(typeof RATES)[number]>(1);\n const onTimeRef = useRef(onTime);\n onTimeRef.current = onTime;\n\n const elements = useCallback(\n () =>\n sources\n .map((source) => audioRefs.current.get(source.trackNumber))\n .filter((element): element is HTMLAudioElement => Boolean(element)),\n [sources],\n );\n const leader = useCallback(() => elements()[0] ?? null, [elements]);\n\n const seek = useCallback(\n (seconds: number) => {\n for (const element of elements()) element.currentTime = seconds;\n setCurrent(seconds);\n onTimeRef.current?.(seconds * 1000);\n },\n [elements],\n );\n const play = useCallback(() => {\n const lead = leader();\n for (const element of elements()) {\n if (lead && element !== lead) element.currentTime = lead.currentTime;\n void element.play().catch(() => setPlaying(false));\n }\n setPlaying(true);\n }, [elements, leader]);\n const pause = useCallback(() => {\n for (const element of elements()) element.pause();\n setPlaying(false);\n }, [elements]);\n\n useImperativeHandle(\n ref,\n () => ({\n playFrom: (milliseconds: number) => {\n seek(milliseconds / 1000);\n play();\n },\n }),\n [play, seek],\n );\n\n useEffect(() => {\n for (const element of elements()) element.playbackRate = rate;\n }, [elements, rate]);\n\n // Follow the leader: time display, transcript highlight and drift correction.\n useEffect(() => {\n const lead = leader();\n if (!lead) return;\n let last = 0;\n const update = () => {\n const now = performance.now();\n if (now - last < 240) return;\n last = now;\n setCurrent(lead.currentTime);\n onTimeRef.current?.(lead.currentTime * 1000);\n for (const element of elements()) {\n if (\n element !== lead &&\n Math.abs(element.currentTime - lead.currentTime) > MAX_DRIFT_SECONDS\n ) {\n element.currentTime = lead.currentTime;\n }\n }\n };\n const ended = () => pause();\n const metadata = () => {\n const longest = Math.max(\n ...elements().map((element) => (Number.isFinite(element.duration) ? element.duration : 0)),\n );\n if (longest > 0) setDuration(longest);\n };\n lead.addEventListener(\"timeupdate\", update);\n lead.addEventListener(\"ended\", ended);\n for (const element of elements()) element.addEventListener(\"loadedmetadata\", metadata);\n return () => {\n lead.removeEventListener(\"timeupdate\", update);\n lead.removeEventListener(\"ended\", ended);\n for (const element of elements()) element.removeEventListener(\"loadedmetadata\", metadata);\n };\n }, [elements, leader, pause]);\n\n const total = Math.max(duration, current);\n const progress = total > 0 ? Math.min(100, (current / total) * 100) : 0;\n const skip = (seconds: number) => seek(Math.min(Math.max(0, current + seconds), total));\n const skipClass =\n \"shrink-0 rounded-full text-fg-muted hover:text-fg pointer-coarse:size-11 max-sm:hidden\";\n return (\n <div\n className={cn(\n \"flex min-w-0 items-center gap-3 rounded-[14px] border border-border bg-surface px-3 py-2 max-sm:gap-2\",\n className,\n )}\n >\n {sources.map((source) => (\n <audio\n key={source.trackNumber}\n ref={(element) => {\n if (element) audioRefs.current.set(source.trackNumber, element);\n else audioRefs.current.delete(source.trackNumber);\n }}\n src={source.url}\n preload=\"metadata\"\n onError={() => onSourceError?.()}\n />\n ))}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => skip(-SKIP_SECONDS)}\n aria-label={msg(\"meetings.player.backCountSeconds\", { count: SKIP_SECONDS })}\n className={skipClass}\n >\n <RotateCcwIcon aria-hidden=\"true\" />\n </Button>\n <Button\n type=\"button\"\n size=\"icon-sm\"\n onClick={() => (playing ? pause() : play())}\n aria-label={playing ? msg(\"meetings.player.pause\") : msg(\"meetings.player.play\")}\n className=\"shrink-0 rounded-full pointer-coarse:size-11\"\n >\n {playing ? (\n <PauseIcon aria-hidden=\"true\" className=\"fill-current\" />\n ) : (\n <PlayIcon aria-hidden=\"true\" className=\"translate-x-px fill-current\" />\n )}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => skip(SKIP_SECONDS)}\n aria-label={msg(\"meetings.player.forwardCountSeconds\", { count: SKIP_SECONDS })}\n className={skipClass}\n >\n <RotateCwIcon aria-hidden=\"true\" />\n </Button>\n <span className=\"min-w-9 shrink-0 text-right text-xs leading-4 text-fg-muted tabular-nums\">\n {formatClock(current * 1000)}\n </span>\n {/* A native range for keyboard and screen readers, drawn with the palette. */}\n <span className=\"relative flex h-6 min-w-0 flex-1 items-center pointer-coarse:h-11\">\n <input\n type=\"range\"\n min={0}\n max={Math.max(1, total)}\n step={0.1}\n value={current}\n onChange={(event) => seek(Number(event.target.value))}\n aria-label={msg(\"meetings.player.position\")}\n aria-valuetext={msg(\"meetings.player.formatclockOfFormatclock2\", {\n formatClock: formatClock(current * 1000),\n formatClock2: formatClock(total * 1000),\n })}\n className=\"peer absolute inset-0 z-10 m-0 h-full w-full cursor-pointer opacity-0\"\n />\n <span aria-hidden=\"true\" className=\"h-1 w-full overflow-hidden rounded-full bg-surface-3\">\n <span className=\"block h-full rounded-full bg-brand\" style={{ width: `${progress}%` }} />\n </span>\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute top-1/2 size-3 -translate-x-1/2 -translate-y-1/2 rounded-full bg-brand shadow-[0_1px_2px_rgb(0_0_0/0.2)] ring-2 ring-surface transition-transform duration-[120ms] peer-hover:scale-125 peer-focus-visible:ring-4 peer-focus-visible:ring-ring/50\"\n style={{ left: `${progress}%` }}\n />\n </span>\n <span className=\"min-w-9 shrink-0 text-xs leading-4 text-fg-muted tabular-nums\">\n {formatClock(total * 1000)}\n </span>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setRate(RATES[(RATES.indexOf(rate) + 1) % RATES.length]!)}\n aria-label={msg(\"meetings.player.playbackSpeedRate\", { rate: rate })}\n title={msg(\"meetings.player.playbackSpeed\")}\n className=\"w-12 min-w-12 shrink-0 justify-center rounded-[8px] px-0 text-xs text-fg-muted tabular-nums pointer-coarse:h-11\"\n >\n {msg(\"meetings.player.rate\", { rate: rate })}\n </Button>\n </div>\n );\n});\n","/**\n * \"Ask about this meeting\": one line at the bottom of the Summary and\n * Transcript tabs. The host answers it, usually by starting a chat with the\n * meeting attached; the input clears once the host has taken the question.\n */\nimport { useOpenGeniText } from \"../messages/runtime\";\nimport { useEffect, useId, useRef, useState } from \"react\";\nimport { ArrowUpIcon, LoaderCircleIcon } from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\n\nimport { Button } from \"../ui/button\";\nimport { TextInput } from \"../ui/field\";\nimport { StickyBarEdge } from \"./sticky-bar-edge\";\n\n/** False when the host couldn't take the question and has already said why. */\nexport type MeetingAskResult = void | boolean;\n\n/**\n * A question from elsewhere in the app, such as the ⌘K menu: asked as if\n * typed here, or, with none, the cursor put in the field.\n */\nexport type MeetingAskRequest = { question: string | null; nonce: number };\n\nexport function MeetingAsk({\n onAsk,\n request = null,\n onRequestTaken,\n}: {\n /**\n * Takes the question. Resolving false keeps it in the input (the host has\n * said why); a rejection keeps it and says the chat couldn't start.\n */\n onAsk: (question: string) => MeetingAskResult | Promise<MeetingAskResult>;\n request?: MeetingAskRequest | null;\n /** The request has been taken, so it isn't acted on again. */\n onRequestTaken?: () => void;\n}) {\n const msg = useOpenGeniText();\n const id = useId();\n const inputRef = useRef<HTMLInputElement>(null);\n const [question, setQuestion] = useState(\"\");\n const [asking, setAsking] = useState(false);\n const trimmed = question.trim();\n const submit = async (text: string = trimmed) => {\n if (!text || asking) return;\n setAsking(true);\n try {\n if ((await onAsk(text)) !== false) setQuestion(\"\");\n } catch (error) {\n toast.error(msg(\"meetings.ask.couldNotAsk\"), {\n description: error instanceof Error ? userErrorText(error) : undefined,\n });\n } finally {\n setAsking(false);\n }\n };\n const submitRef = useRef(submit);\n submitRef.current = submit;\n const takenRef = useRef(onRequestTaken);\n takenRef.current = onRequestTaken;\n useEffect(() => {\n if (!request) return;\n takenRef.current?.();\n const text = request.question?.trim();\n if (text) {\n setQuestion(text);\n void submitRef.current(text);\n return;\n }\n inputRef.current?.focus({ preventScroll: true });\n inputRef.current?.scrollIntoView?.({ block: \"nearest\" });\n }, [request]);\n return (\n // Stays in reach at the bottom of the window while the tab scrolls. It ends\n // its column, so the page under it is covered all the way to the window's edge.\n <form\n aria-label={msg(\"meetings.ask.placeholder\")}\n className=\"sticky bottom-0 z-10 -mx-1 bg-bg px-1 pt-3 pb-4\"\n onSubmit={(event) => {\n event.preventDefault();\n void submit();\n }}\n >\n <StickyBarEdge edge=\"bottom\" />\n <div className=\"relative\">\n <label htmlFor={id} className=\"sr-only\">\n {msg(\"meetings.ask.placeholder\")}\n </label>\n <TextInput\n ref={inputRef}\n id={id}\n value={question}\n maxLength={4000}\n autoComplete=\"off\"\n disabled={asking}\n placeholder={msg(\"meetings.ask.placeholder\")}\n onChange={(event) => setQuestion(event.target.value)}\n className=\"h-11 rounded-[14px]! pr-12 shadow-og-sm\"\n />\n <Button\n type=\"submit\"\n size=\"icon-sm\"\n disabled={!trimmed || asking}\n aria-label={msg(\"meetings.ask.send\")}\n className=\"absolute top-1/2 right-1.5 size-8 -translate-y-1/2 rounded-[10px] pointer-coarse:size-9\"\n >\n {asking ? (\n <LoaderCircleIcon\n aria-hidden=\"true\"\n className=\"animate-spin motion-reduce:animate-none\"\n />\n ) : (\n <ArrowUpIcon aria-hidden=\"true\" />\n )}\n </Button>\n </div>\n </form>\n );\n}\n","import { useEffect, useState } from \"react\";\n\n/**\n * A sticky bar stops at its scroll container's padding. A host page that pads\n * its scroller (room for its own floating button, say) would show the page\n * scrolling past in the strip between the bar and the window's edge. This\n * paints the page background over that strip, as if the bar reached the edge.\n * It is a clipped shadow, so it adds no scroll length and catches no clicks.\n * Render it inside the sticky bar (which is positioned) and only while the bar\n * is pinned against `edge`; a bar that only ever ends its column can keep it.\n */\nexport function StickyBarEdge({ edge }: { edge: \"top\" | \"bottom\" }) {\n const down = edge === \"bottom\";\n return (\n <span\n aria-hidden\n data-og-sticky-edge={edge}\n className=\"pointer-events-none absolute inset-0\"\n style={{\n boxShadow: `0 ${down ? \"\" : \"-\"}50vh 0 50vh var(--color-bg)`,\n clipPath: down ? \"inset(0 0 -100vh 0)\" : \"inset(-100vh 0 0 0)\",\n }}\n />\n );\n}\n\n/** True while a sticky `top-0` bar is pinned to the top of its scroll container. */\nexport function useStuckToTop(bar: HTMLElement | null): boolean {\n const [stuck, setStuck] = useState(false);\n useEffect(() => {\n if (!bar) return;\n const scroller = scrollContainerOf(bar);\n let frame = 0;\n const measure = () => {\n frame = 0;\n setStuck(pinnedToTop(bar, scroller));\n };\n const schedule = () => {\n if (!frame) frame = requestAnimationFrame(measure);\n };\n measure();\n const target: HTMLElement | Window = scroller ?? window;\n target.addEventListener(\"scroll\", schedule, { passive: true });\n window.addEventListener(\"resize\", schedule);\n return () => {\n if (frame) cancelAnimationFrame(frame);\n target.removeEventListener(\"scroll\", schedule);\n window.removeEventListener(\"resize\", schedule);\n };\n }, [bar]);\n return stuck;\n}\n\n/** The nearest ancestor that scrolls vertically; null when the page itself scrolls. */\nexport function scrollContainerOf(node: HTMLElement): HTMLElement | null {\n for (let parent = node.parentElement; parent; parent = parent.parentElement) {\n if (parent === document.body || parent === document.documentElement) return null;\n const overflow = getComputedStyle(parent).overflowY;\n if (overflow === \"auto\" || overflow === \"scroll\" || overflow === \"overlay\") return parent;\n }\n return null;\n}\n\n/**\n * Pinned means the bar's top sits on the scroller's content edge (inside its\n * padding), where `top: 0` holds it; unpinned, it sits lower, in its own place.\n */\nexport function pinnedToTop(bar: HTMLElement, scroller: HTMLElement | null): boolean {\n const top = bar.getBoundingClientRect().top;\n if (!scroller) return top <= 1;\n const view = scroller.getBoundingClientRect();\n const padding = Number.parseFloat(getComputedStyle(scroller).paddingTop) || 0;\n return top <= view.top + scroller.clientTop + padding + 1;\n}\n","/**\n * Mentions in a meeting's written notes. The notes are Markdown, and an agent\n * (or a person) names someone with a link of exactly one of two forms:\n *\n * - `[Display name](speaker:<speakerLabel>)`: a voice in this meeting, such\n * as `speaker:speaker_0` or `speaker:track-0`.\n * - `[Display name](person:<personId>)`: someone in the people directory.\n *\n * Each shows as a small chip with the current name, so renaming a speaker or\n * a person updates the notes without rewriting them. A label or id this\n * meeting doesn't know shows the link text as plain text, never a link.\n */\nimport type { ReactNode } from \"react\";\nimport type { RecordingPerson, RecordingSpeaker, RecordingTrack } from \"@opengeni/contracts\";\n\nimport type { OpenGeniLinkRenderer } from \"../components/open-geni-links\";\nimport { createOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\nimport { speakerDisplayName } from \"../recordings\";\nimport { cn } from \"../app/lib/utils\";\n\nimport {\n SpeakerDot,\n speakerHueStyle,\n speakerTextClass,\n speakerTintClass,\n} from \"./meeting-transcript\";\n\nconst defaultText = createOpenGeniText();\n\nexport type MeetingMention =\n | { kind: \"speaker\"; label: string }\n | { kind: \"person\"; personId: string };\n\n/** Who a mention names now: the current name and, for a voice, its colour slot. */\nexport type ResolvedMeetingMention = { name: string; slot: number | undefined };\n\nexport type MeetingMentionResolver = (mention: MeetingMention) => ResolvedMeetingMention | null;\n\nconst MENTION_HREF = /^(speaker|person):(\\S+)$/u;\n\n/** The mention a link points at, or null when it is any other link. */\nexport function parseMeetingMention(href: string | null | undefined): MeetingMention | null {\n const match = MENTION_HREF.exec(href ?? \"\");\n if (!match) return null;\n let value = match[2]!;\n try {\n value = decodeURIComponent(value);\n } catch {\n // Not percent-encoded after all; keep it as written.\n }\n return match[1] === \"speaker\"\n ? { kind: \"speaker\", label: value }\n : { kind: \"person\", personId: value };\n}\n\n/**\n * Resolves mentions against this meeting: a speaker label it has (named or\n * heard in the transcript), or a person in the directory or named here.\n */\nexport function meetingMentionResolver({\n speakers,\n tracks,\n people,\n slots,\n msg = defaultText,\n}: {\n speakers: readonly RecordingSpeaker[];\n tracks: readonly RecordingTrack[];\n people: readonly RecordingPerson[];\n /** The transcript's colour slot per speaker label. */\n slots: ReadonlyMap<string, number>;\n msg?: OpenGeniText;\n}): MeetingMentionResolver {\n return (mention) => {\n if (mention.kind === \"speaker\") {\n const known =\n slots.has(mention.label) || speakers.some((speaker) => speaker.label === mention.label);\n if (!known) return null;\n return {\n name: speakerDisplayName(mention.label, speakers, tracks, msg),\n slot: slots.get(mention.label),\n };\n }\n // A person who spoke here takes that voice's colour.\n const voice = speakers.find((speaker) => speaker.personId === mention.personId);\n const slot = voice ? slots.get(voice.label) : undefined;\n const person = people.find((candidate) => candidate.id === mention.personId);\n if (person?.displayName.trim()) return { name: person.displayName, slot };\n if (voice?.name.trim()) return { name: voice.name, slot };\n return null;\n };\n}\n\n/**\n * What Copy looks at, in reading order: a fenced code block, a code span or\n * an image (each kept as written, as the page draws them literally), or a\n * mention `[text](speaker:…)` / `[text](person:…)`, with `\\]`-escaped\n * brackets in the text. A code span, like on the page, never crosses a blank\n * line.\n */\nconst COPY_SCAN =\n /^ {0,3}(?<mark>`{3,}|~{3,})[^\\n]*[\\s\\S]*?(?:\\n {0,3}\\k<mark>[`~]*[ \\t]*(?=\\n|(?![\\s\\S]))|(?![\\s\\S]))|(?<ticks>`+)(?:(?!\\n[ \\t]*\\n)[\\s\\S])*?\\k<ticks>(?!`)|!\\[(?:\\\\.|[^\\\\\\]])*\\]\\([^)]*\\)|\\[(?<text>(?:\\\\.|[^\\\\\\]])*)\\]\\((?<kind>speaker|person):(?<value>[^()\\s]+)\\)/gmu;\n\n/** Link text as it reads: Markdown escapes removed. */\nfunction unescapeLinkText(text: string): string {\n return text.replace(/\\\\([\\\\`*_{}[\\]()#+\\-.!|<>~])/gu, \"$1\");\n}\n\n/**\n * The notes as Markdown with each mention turned into the plain current\n * name (or its link text when this meeting doesn't know it), for copying.\n */\nexport function meetingNotesForCopy(markdown: string, resolve: MeetingMentionResolver): string {\n return markdown.replace(COPY_SCAN, (...args: unknown[]) => {\n const match = args[0] as string;\n const { text, kind, value } = args.at(-1) as Partial<Record<string, string>>;\n // Code and images stay as they are.\n if (text === undefined || kind === undefined || value === undefined) return match;\n const mention = parseMeetingMention(`${kind}:${value}`);\n const resolved = mention ? resolve(mention) : null;\n return resolved ? resolved.name : unescapeLinkText(text);\n });\n}\n\n/** A mention as a small inline chip: a voice in its colour, a person plain. */\nexport function MeetingMentionChip({\n mention,\n name,\n slot,\n}: {\n mention: MeetingMention;\n name: string;\n slot: number | undefined;\n}) {\n return (\n <span\n data-mention={mention.kind}\n className={cn(\n \"inline-flex max-w-full items-center gap-1 rounded-full px-1.5 align-baseline text-[0.93em] leading-[1.45] font-medium whitespace-nowrap\",\n slot === undefined\n ? \"bg-surface-2 text-fg\"\n : [speakerTintClass(slot), speakerTextClass(slot)],\n )}\n style={speakerHueStyle(slot)}\n >\n {slot !== undefined ? <SpeakerDot slot={slot} className=\"size-1.5\" /> : null}\n <span className=\"min-w-0 truncate\">{name}</span>\n </span>\n );\n}\n\n/**\n * Draws mention links as chips for {@link Markdown}'s `renderLink`, and any\n * mention this meeting doesn't know as its plain text. Other links fall\n * through to the default renderer.\n */\nexport function meetingMentionLinkRenderer(resolve: MeetingMentionResolver): OpenGeniLinkRenderer {\n return ({ href, children }): ReactNode | undefined => {\n const mention = parseMeetingMention(href);\n if (!mention) return undefined;\n const resolved = resolve(mention);\n if (!resolved) return <>{children}</>;\n return <MeetingMentionChip mention={mention} name={resolved.name} slot={resolved.slot} />;\n };\n}\n","/**\n * A meeting's notes: the written-up notes (summary, decisions, action items)\n * shown as Markdown with Edit, and the notepad people jot into while the\n * meeting is recorded, which saves as they type.\n *\n * The meeting page shows them as its Summary and Notepad tabs. While the\n * meeting is being recorded here they share one Notes section, notepad\n * first. Notes an agent wrote say so and link to its chat; mentions of\n * speakers and people show as chips (see ./meeting-mentions).\n */\nimport { useOpenGeniText } from \"../messages/runtime\";\nimport { useEffect, useId, useMemo, useRef, useState, type ComponentProps } from \"react\";\nimport { BotIcon, CheckIcon, CopyIcon, LoaderCircleIcon, PencilIcon } from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\nimport type { RecordingNote } from \"@opengeni/contracts\";\nimport { OpenGeniApiError } from \"@opengeni/sdk\";\nimport { Markdown } from \"../components/markdown\";\nimport {\n useRecordingNotes,\n type RecordingsClientOverride,\n type UseRecordingNotesResult,\n} from \"../recordings\";\nimport { copyTextToClipboard } from \"../lib/clipboard\";\nimport { Button } from \"../ui/button\";\nimport { DetailSection } from \"../ui/detail-sheet\";\nimport { TextArea } from \"../ui/field\";\nimport { Notice } from \"../ui/notice\";\nimport { formatAbsoluteTime } from \"../ui/relative-time\";\nimport { Skeleton } from \"../ui/skeleton\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\n\nimport {\n meetingMentionLinkRenderer,\n meetingNotesForCopy,\n type MeetingMentionResolver,\n} from \"./meeting-mentions\";\n\n/** How long typing pauses before the notepad saves. */\nexport const NOTEPAD_SAVE_DELAY_MS = 800;\n\nfunction isNotesChanged(error: unknown): boolean {\n return (\n error instanceof OpenGeniApiError &&\n error.status === 409 &&\n error.details?.code === \"notes_changed\"\n );\n}\n\nfunction errorText(error: unknown): string | undefined {\n return error instanceof Error ? userErrorText(error) : undefined;\n}\n\nfunction MeetingNotesContent({\n recordingId,\n recording: override,\n capturing,\n onOpenChat,\n}: {\n recordingId: string;\n recording: RecordingsClientOverride;\n /** The meeting is being recorded now, so the notepad comes first. */\n capturing: boolean;\n /** Opens the chat whose agent wrote the notes. */\n onOpenChat?: ((sessionId: string) => void) | undefined;\n}) {\n const notes = useRecordingNotes(recordingId, override);\n return <MeetingNotesSection notes={notes} capturing={capturing} onOpenChat={onOpenChat} />;\n}\n\n/** The Notes section over notes the page already loads: notepad and written notes together. */\nexport function MeetingNotesSection({\n notes,\n capturing,\n onOpenChat,\n mentions,\n}: {\n notes: UseRecordingNotesResult;\n /** The meeting is being recorded now, so the notepad comes first. */\n capturing: boolean;\n onOpenChat?: ((sessionId: string) => void) | undefined;\n /** Resolves speaker and person mentions in the written notes. */\n mentions?: MeetingMentionResolver | null | undefined;\n}) {\n const msg = useOpenGeniText();\n const [editing, setEditing] = useState(false);\n\n if (notes.loading && !notes.notes && !notes.notepad) {\n return (\n <DetailSection title={msg(\"meetings.notes.title\")}>\n <NotesSkeleton />\n </DetailSection>\n );\n }\n\n const written = (\n <WrittenNotes\n note={notes.notes}\n editing={editing}\n onEdit={() => setEditing(true)}\n onDone={() => setEditing(false)}\n save={(body) => notes.save(\"notes\", body)}\n refresh={notes.refresh}\n onOpenChat={onOpenChat}\n mentions={mentions}\n />\n );\n const notepad = (\n <Notepad\n note={notes.notepad}\n rows={capturing ? 6 : 3}\n // Alone under the Notes heading while recording, it needs no second heading.\n labelHidden={capturing && !notes.notes}\n save={(body) => notes.save(\"notepad\", body)}\n />\n );\n\n return (\n <DetailSection\n title={msg(\"meetings.notes.title\")}\n action={\n notes.notes && !editing ? (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => setEditing(true)}\n className=\"pointer-coarse:h-11\"\n >\n <PencilIcon aria-hidden=\"true\" />\n {msg(\"meetings.notes.edit\")}\n </Button>\n ) : undefined\n }\n >\n <div className=\"grid gap-6\">\n {capturing ? (\n <>\n {notepad}\n {notes.notes ? written : null}\n </>\n ) : (\n <>\n {written}\n {notepad}\n </>\n )}\n </div>\n </DetailSection>\n );\n}\n\nfunction NotesSkeleton() {\n return (\n <div aria-busy=\"true\" className=\"grid gap-2\">\n <Skeleton className=\"h-4 w-2/3\" />\n <Skeleton className=\"h-4 w-1/2\" />\n </div>\n );\n}\n\n/**\n * The Summary tab: the written notes as Markdown, who wrote them, Copy and\n * Edit. Mentions of speakers and people show as chips with current names.\n */\nexport function MeetingSummary({\n notes,\n onOpenChat,\n mentions,\n}: {\n notes: UseRecordingNotesResult;\n onOpenChat?: ((sessionId: string) => void) | undefined;\n mentions: MeetingMentionResolver | null;\n}) {\n const msg = useOpenGeniText();\n const [editing, setEditing] = useState(false);\n // A reload (such as after the window was hidden) never replaces an edit.\n if (notes.loading && !notes.notes && !editing) return <NotesSkeleton />;\n const note = notes.notes;\n const hasBody = Boolean(note?.body.trim());\n return (\n <div className=\"grid gap-4\">\n {note && hasBody && !editing ? (\n <div className=\"flex min-w-0 flex-wrap items-center justify-between gap-x-4 gap-y-1\">\n <NotesAttribution note={note} onOpenChat={onOpenChat} />\n <div className=\"ml-auto flex shrink-0 items-center gap-1\">\n <CopyNotesButton\n text={() => (mentions ? meetingNotesForCopy(note.body, mentions) : note.body)}\n />\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => setEditing(true)}\n className=\"pointer-coarse:h-11\"\n >\n <PencilIcon aria-hidden=\"true\" />\n {msg(\"meetings.notes.edit\")}\n </Button>\n </div>\n </div>\n ) : null}\n <WrittenNotes\n note={note}\n editing={editing}\n onEdit={() => setEditing(true)}\n onDone={() => setEditing(false)}\n save={(body) => notes.save(\"notes\", body)}\n refresh={notes.refresh}\n onOpenChat={onOpenChat}\n mentions={mentions}\n attribution={false}\n />\n </div>\n );\n}\n\n/** The Notepad tab: what people jot down, saved as they type. */\nexport function MeetingNotepad({ notes }: { notes: UseRecordingNotesResult }) {\n if (notes.loading && !notes.notepad) return <NotesSkeleton />;\n return (\n <Notepad\n note={notes.notepad}\n rows={10}\n labelHidden\n save={(body) => notes.save(\"notepad\", body)}\n />\n );\n}\n\nconst COPIED_MS = 1600;\n\n/** Copies the notes, then says Copied for a moment. */\nfunction CopyNotesButton({ text }: { text: () => string }) {\n const msg = useOpenGeniText();\n const [copied, setCopied] = useState(false);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(\n () => () => {\n if (timer.current) clearTimeout(timer.current);\n },\n [],\n );\n return (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={() =>\n void copyTextToClipboard(text()).then((ok) => {\n if (!ok) {\n toast.error(msg(\"meetings.notes.couldNotCopy\"));\n return;\n }\n setCopied(true);\n if (timer.current) clearTimeout(timer.current);\n timer.current = setTimeout(() => setCopied(false), COPIED_MS);\n })\n }\n className=\"pointer-coarse:h-11\"\n >\n {copied ? <CheckIcon aria-hidden=\"true\" /> : <CopyIcon aria-hidden=\"true\" />}\n <span aria-live=\"polite\">\n {copied ? msg(\"meetings.notes.copied\") : msg(\"meetings.notes.copy\")}\n </span>\n </Button>\n );\n}\n\n/** \"Written by an agent · time · Open the chat\", or \"Edited · time\". */\nfunction NotesAttribution({\n note,\n onOpenChat,\n}: {\n note: RecordingNote;\n onOpenChat?: ((sessionId: string) => void) | undefined;\n}) {\n const msg = useOpenGeniText();\n const sessionId = note.updatedBy.sessionId;\n return (\n <p className=\"flex flex-wrap items-center gap-x-2 gap-y-1 text-xs leading-4 text-fg-muted\">\n {sessionId ? (\n <>\n <BotIcon aria-hidden=\"true\" className=\"size-3.5\" />\n <span>\n {msg(\"meetings.notes.writtenByAgent\", {\n time: formatAbsoluteTime(note.updatedAt, { text: msg }),\n })}\n </span>\n {onOpenChat ? (\n <button\n type=\"button\"\n onClick={() => onOpenChat(sessionId)}\n className=\"font-medium text-fg-label underline-offset-2 hover:underline pointer-coarse:min-h-11\"\n >\n {msg(\"meetings.notes.openChat\")}\n </button>\n ) : null}\n </>\n ) : (\n <span>\n {msg(\"meetings.notes.edited\", {\n time: formatAbsoluteTime(note.updatedAt, { text: msg }),\n })}\n </span>\n )}\n </p>\n );\n}\n\nfunction WrittenNotes({\n note,\n editing,\n onEdit,\n onDone,\n save,\n refresh,\n onOpenChat,\n mentions,\n attribution = true,\n}: {\n note: RecordingNote | null;\n editing: boolean;\n onEdit: () => void;\n onDone: () => void;\n save: (body: string) => Promise<RecordingNote>;\n refresh: () => Promise<void>;\n onOpenChat?: ((sessionId: string) => void) | undefined;\n mentions?: MeetingMentionResolver | null | undefined;\n /** Say who wrote them under the notes; the Summary tab says it in its header. */\n attribution?: boolean;\n}) {\n const msg = useOpenGeniText();\n const [draft, setDraft] = useState(note?.body ?? \"\");\n const [saving, setSaving] = useState(false);\n const [changedMeanwhile, setChangedMeanwhile] = useState(false);\n const editorId = useId();\n const renderLink = useMemo(\n // Without a resolver, mentions read as their link text, never a dead link.\n () => meetingMentionLinkRenderer(mentions ?? (() => null)),\n [mentions],\n );\n\n useEffect(() => {\n // Start each edit from the notes as they are now.\n if (editing) {\n setDraft(note?.body ?? \"\");\n setChangedMeanwhile(false);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editing]);\n\n if (editing) {\n const submit = async () => {\n setSaving(true);\n try {\n await save(draft);\n onDone();\n toast.success(msg(\"meetings.notes.saved\"));\n } catch (error) {\n if (isNotesChanged(error)) {\n // Load theirs so a second Save replaces it knowingly.\n await refresh();\n setChangedMeanwhile(true);\n } else {\n toast.error(msg(\"meetings.notes.couldNotSave\"), { description: errorText(error) });\n }\n } finally {\n setSaving(false);\n }\n };\n return (\n <div className=\"grid gap-3\">\n <label htmlFor={editorId} className=\"sr-only\">\n {msg(\"meetings.notes.editorLabel\")}\n </label>\n <TextArea\n id={editorId}\n rows={10}\n mono\n autoFocus\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n placeholder={msg(\"meetings.notes.editorPlaceholder\")}\n className=\"max-h-[60vh]\"\n />\n {changedMeanwhile ? (\n <Notice tone=\"info\">{msg(\"meetings.notes.changedMeanwhile\")}</Notice>\n ) : null}\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={saving}\n onClick={() => void submit()}\n className=\"pointer-coarse:h-11\"\n >\n {saving ? <LoaderCircleIcon aria-hidden=\"true\" className=\"animate-spin\" /> : null}\n {changedMeanwhile ? msg(\"meetings.notes.saveAnyway\") : msg(\"meetings.notes.save\")}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n disabled={saving}\n onClick={onDone}\n className=\"pointer-coarse:h-11\"\n >\n {msg(\"meetings.notes.cancel\")}\n </Button>\n <span className=\"text-xs leading-4 text-fg-muted\">\n {msg(\"meetings.notes.markdownHint\")}\n </span>\n </div>\n </div>\n );\n }\n\n if (!note || !note.body.trim()) {\n return (\n <div className=\"grid justify-items-start gap-3\">\n <p className=\"text-sm leading-5 text-fg-muted\">{msg(\"meetings.notes.empty\")}</p>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={onEdit}\n className=\"pointer-coarse:h-11\"\n >\n <PencilIcon aria-hidden=\"true\" />\n {msg(\"meetings.notes.write\")}\n </Button>\n </div>\n );\n }\n\n return (\n <div className=\"grid gap-3\">\n <Markdown className=\"text-sm\" renderLink={renderLink}>\n {note.body}\n </Markdown>\n {attribution ? <NotesAttribution note={note} onOpenChat={onOpenChat} /> : null}\n </div>\n );\n}\n\ntype NotepadStatus = \"idle\" | \"saving\" | \"saved\" | \"failed\";\n\nfunction Notepad({\n note,\n rows,\n labelHidden = false,\n save,\n}: {\n note: RecordingNote | null;\n rows: number;\n /** A heading or tab above already names it. */\n labelHidden?: boolean;\n save: (body: string) => Promise<RecordingNote>;\n}) {\n const msg = useOpenGeniText();\n const id = useId();\n const [draft, setDraft] = useState(note?.body ?? \"\");\n const [status, setStatus] = useState<NotepadStatus>(\"idle\");\n // What the server last confirmed, and whether the reader has typed since.\n const saved = useRef(note?.body ?? \"\");\n const dirty = useRef(false);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const saveRef = useRef(save);\n saveRef.current = save;\n\n // Text saved elsewhere arrives while nobody is typing here.\n useEffect(() => {\n const body = note?.body ?? \"\";\n if (!dirty.current && body !== saved.current) {\n saved.current = body;\n setDraft(body);\n }\n }, [note?.body]);\n\n const flush = (body: string) => {\n if (timer.current) clearTimeout(timer.current);\n timer.current = null;\n if (body === saved.current) {\n dirty.current = false;\n return;\n }\n setStatus(\"saving\");\n void saveRef.current(body).then(\n () => {\n saved.current = body;\n dirty.current = false;\n setStatus(\"saved\");\n },\n () => setStatus(\"failed\"),\n );\n };\n\n // Leaving the page saves what was typed last.\n const latest = useRef(draft);\n latest.current = draft;\n useEffect(\n () => () => {\n if (timer.current) flush(latest.current);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n );\n\n const statusText = (\n <span role=\"status\" aria-live=\"polite\" className=\"text-xs leading-4 text-fg-muted\">\n {status === \"saving\"\n ? msg(\"meetings.notes.notepadSaving\")\n : status === \"saved\"\n ? msg(\"meetings.notes.notepadSaved\")\n : status === \"failed\"\n ? msg(\"meetings.notes.notepadFailed\")\n : null}\n </span>\n );\n\n return (\n <div className=\"grid gap-2\">\n {labelHidden ? (\n <label htmlFor={id} className=\"sr-only\">\n {msg(\"meetings.notes.notepad\")}\n </label>\n ) : (\n <div className=\"flex items-baseline justify-between gap-3\">\n <label htmlFor={id} className=\"text-sm leading-5 font-medium text-fg\">\n {msg(\"meetings.notes.notepad\")}\n </label>\n {statusText}\n </div>\n )}\n <TextArea\n id={id}\n rows={rows}\n value={draft}\n placeholder={msg(\"meetings.notes.notepadPlaceholder\")}\n onChange={(event) => {\n const body = event.target.value;\n setDraft(body);\n dirty.current = true;\n setStatus(\"idle\");\n if (timer.current) clearTimeout(timer.current);\n timer.current = setTimeout(() => flush(body), NOTEPAD_SAVE_DELAY_MS);\n }}\n onBlur={() => flush(draft)}\n />\n {labelHidden ? <div className=\"flex min-h-4 justify-end\">{statusText}</div> : null}\n {status === \"failed\" ? (\n <button\n type=\"button\"\n onClick={() => flush(draft)}\n className=\"w-fit text-xs leading-4 font-medium text-fg-label underline-offset-2 hover:underline pointer-coarse:min-h-11\"\n >\n {msg(\"meetings.notes.notepadRetry\")}\n </button>\n ) : null}\n </div>\n );\n}\n\nexport function MeetingNotes(props: ComponentProps<typeof MeetingNotesContent>) {\n return (\n <MeetingsOverlayScope>\n <MeetingNotesContent {...props} />\n </MeetingsOverlayScope>\n );\n}\n","// Workspace settings → General → Meetings: who sees new meetings, which\n// model transcribes them, whether an agent writes their notes, and whether\n// people are recognized by voice. All live under the workspace's\n// `recordings` settings, which a patch replaces as a whole.\nimport { useOpenGeniText, createOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\nimport { regionRestrictedText } from \"../inference-region\";\nimport { useState, type ComponentProps } from \"react\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\n\nimport {\n type RecordingPerson,\n type RecordingRetention,\n type RecordingTranscriptionModel,\n type RecordingVisibility,\n type WorkspaceRecordingSettings,\n} from \"@opengeni/contracts\";\nimport {\n languageName,\n useRecordingModels,\n useRecordingPeople,\n type RecordingsClientOverride,\n} from \"../recordings\";\nimport { Button } from \"../ui/button\";\nimport { ConfirmDialog } from \"../ui/confirm-dialog\";\nimport { Section } from \"../ui/section\";\nimport { WordListRow } from \"../ui/word-list-row\";\nimport { SegmentedControl } from \"../ui/segmented-control\";\nimport { NativeSelect, type SelectOption } from \"../ui/select-menu\";\nimport { SettingRow, SettingRowLink } from \"../ui/setting-row\";\nimport { Switch } from \"../ui/switch\";\n\nimport { DETECT_LANGUAGE, meetingLanguageOptions } from \"./meeting-languages\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\n\nconst defaultText = createOpenGeniText();\n\nconst DEFAULT = \"default\";\nconst KEEP = \"keep\";\n\nconst AUDIO_PERIODS = [0, 7, 30, 90, 365] as const;\nconst MEETING_PERIODS = [30, 90, 180, 365, 730] as const;\n\n/** What a model costs and who pays, beside its name in the picker. */\nexport function transcriptionModelMeta(\n entry: RecordingTranscriptionModel,\n msg: OpenGeniText = defaultText,\n): string {\n if (entry.funding === \"workspace_subscription\") return msg(\"meetings.settings.yourSubscription\");\n if (entry.usdPerHour !== null && entry.usdPerHour > 0) {\n return msg(\"meetings.settings.valuePerHour\", { value: entry.usdPerHour.toFixed(2) });\n }\n return entry.providerName;\n}\n\n/** Why a model can't be picked yet, and what makes it pickable. */\nexport function transcriptionModelUnavailableReason(\n entry: RecordingTranscriptionModel,\n msg: OpenGeniText = defaultText,\n): string {\n const regionRestricted = regionRestrictedText(msg, entry.unavailableReason);\n if (regionRestricted) return regionRestricted;\n const providerName = entry.providerName;\n switch (entry.funding) {\n case \"workspace_subscription\":\n return msg(\"meetings.settings.connectYourProvidernameFirst\", { providerName });\n case \"workspace_key\":\n return msg(\"meetings.settings.connectProvidernameFirst\", { providerName });\n case \"deployment\":\n return msg(\"meetings.settings.providernameIsnTAvailableHere\", { providerName });\n }\n}\n\n/**\n * \"Not supported in EU\" when no live model is available and the server\n * switched them off for the region, otherwise null.\n */\nexport function liveTranscriptRestriction(\n liveModels: readonly Pick<RecordingTranscriptionModel, \"available\" | \"unavailableReason\">[],\n msg: OpenGeniText = defaultText,\n): string | null {\n if (liveModels.some((entry) => entry.available)) return null;\n return regionRestrictedText(\n msg,\n liveModels.find((entry) => entry.unavailableReason)?.unavailableReason,\n );\n}\n\n/** \"30 days\", \"1 year\", \"2 years\". */\nexport function retentionPeriodName(days: number, msg: OpenGeniText = defaultText): string {\n if (days % 365 === 0) return msg(\"meetings.settings.countYears\", { count: days / 365 });\n return msg(\"meetings.settings.countDays\", { count: days });\n}\n\n/**\n * The confirmation for a retention change that deletes what's already\n * recorded, or null when the change deletes nothing sooner than before.\n */\nexport function retentionChangeWarning(\n before: RecordingRetention | undefined,\n after: RecordingRetention,\n msg: OpenGeniText = defaultText,\n): { title: string; description: string; confirmLabel: string } | null {\n const shorter = (previous: number | undefined, next: number | undefined) =>\n next !== undefined && (previous === undefined || next < previous);\n if (shorter(before?.transcriptDays, after.transcriptDays)) {\n const period = retentionPeriodName(after.transcriptDays!, msg);\n return {\n title: msg(\"meetings.settings.deleteMeetingsAfterPeriod\", { period: period }),\n description: msg(\"meetings.settings.meetingsRecordedMoreThanPeriod\", {\n period: period,\n }),\n confirmLabel: msg(\"meetings.settings.deleteOldMeetings\"),\n };\n }\n if (shorter(before?.audioDays, after.audioDays)) {\n const days = after.audioDays!;\n return {\n title:\n days === 0\n ? msg(\"meetings.settings.deleteAudioOnceTranscribed\")\n : msg(\"meetings.settings.deleteAudioAfterRetentionperiodname\", {\n retentionPeriodName: retentionPeriodName(days, msg),\n }),\n description:\n days === 0\n ? msg(\"meetings.settings.theAudioOfEveryTranscribed\")\n : msg(\"meetings.settings.theAudioOfMeetingsRecorded\", {\n retentionPeriodName: retentionPeriodName(days, msg),\n }),\n confirmLabel:\n days === 0\n ? msg(\"meetings.settings.deleteTranscribedAudio\")\n : msg(\"meetings.settings.deleteOldAudio\"),\n };\n }\n return null;\n}\n\n/** Who is looking at the settings, so they can agree to have their own voice remembered. */\nexport type MeetingSettingsViewer = { subjectId: string; name: string };\n\nfunction MeetingDefaultsViewContent({\n workspaceId,\n settings: current,\n personal,\n canManage,\n viewer,\n onConnectModels,\n onSave,\n recordings,\n}: {\n workspaceId: string;\n settings: WorkspaceRecordingSettings;\n personal: boolean;\n canManage: boolean;\n viewer: MeetingSettingsViewer;\n onConnectModels?: (() => void) | undefined;\n /** Saves the whole `recordings` settings; false when a newer change took over. */\n onSave: (next: WorkspaceRecordingSettings) => Promise<boolean>;\n /** A recordings client to use instead of the app's, for previews. */\n recordings?: RecordingsClientOverride[\"recordings\"];\n}) {\n const msg = useOpenGeniText();\n const models = useRecordingModels({ workspaceId, ...(recordings ? { recordings } : {}) });\n const [saving, setSaving] = useState(false);\n const reason = canManage ? undefined : msg(\"meetings.settings.onlyWorkspaceAdminsCanChange\");\n\n /** False when the change failed or a newer one took over. */\n async function save(next: WorkspaceRecordingSettings, success: string): Promise<boolean> {\n setSaving(true);\n try {\n const saved = await onSave(next);\n if (saved) toast.success(success);\n return saved;\n } catch {\n toast.error(msg(\"meetings.settings.couldnTUpdateMeetingSettings\"));\n return false;\n } finally {\n setSaving(false);\n }\n }\n\n const visibility: RecordingVisibility = current.defaultVisibility ?? \"private\";\n const chooseVisibility = (next: RecordingVisibility) => {\n if (next === visibility) return;\n const { defaultVisibility: _previous, ...rest } = current;\n void save(\n next === \"private\" ? rest : { ...rest, defaultVisibility: next },\n next === \"workspace\"\n ? msg(\"meetings.settings.newMeetingsAreSharedWith\")\n : msg(\"meetings.settings.newMeetingsArePrivate\"),\n );\n };\n\n const fallback = models.defaultModel;\n const fallbackName =\n models.models.find(\n (entry) => entry.providerId === fallback?.providerId && entry.model === fallback?.model,\n )?.name ?? null;\n const chosen = current.transcription\n ? `${current.transcription.providerId}/${current.transcription.model}`\n : DEFAULT;\n const modelOptions: SelectOption[] = [\n {\n value: DEFAULT,\n // A pinned deployment has only that model, so it is not a default.\n label: fallbackName\n ? models.pinned\n ? fallbackName\n : msg(\"meetings.settings.defaultFallbackname\", { fallbackName: fallbackName })\n : msg(\"meetings.settings.default\"),\n },\n ...models.models.map((entry) => ({\n value: `${entry.providerId}/${entry.model}`,\n label: entry.name,\n meta: transcriptionModelMeta(entry, msg),\n disabled: !entry.available,\n disabledReason: entry.available ? undefined : transcriptionModelUnavailableReason(entry, msg),\n })),\n ];\n const chooseModel = (value: string) => {\n if (value === chosen) return;\n const { transcription: _previous, ...rest } = current;\n const entry = models.models.find(\n (candidate) => `${candidate.providerId}/${candidate.model}` === value,\n );\n void save(\n entry\n ? { ...rest, transcription: { providerId: entry.providerId, model: entry.model } }\n : rest,\n entry\n ? msg(\"meetings.settings.newMeetingsUseName\", { name: entry.name })\n : msg(\"meetings.settings.newMeetingsUseTheDefault\"),\n );\n };\n const noneAvailable =\n !models.loading && !models.error && !models.models.some((entry) => entry.available);\n\n const language = current.language ?? DETECT_LANGUAGE;\n const chooseLanguage = (value: string) => {\n if (value === language) return;\n const { language: _previous, ...rest } = current;\n void save(\n value === DETECT_LANGUAGE ? rest : { ...rest, language: value },\n value === DETECT_LANGUAGE\n ? msg(\"meetings.settings.newMeetingsDetectTheirLanguage\")\n : msg(\"meetings.settings.newMeetingsAreTranscribedIn\", {\n languageName: languageName(value, msg.locale),\n }),\n );\n };\n\n const voiceprints = current.voiceprints === true;\n\n const keyterms = current.keyterms ?? [];\n const chooseKeyterms = (next: string[]) => {\n const { keyterms: _previous, ...rest } = current;\n void save(\n next.length > 0 ? { ...rest, keyterms: next } : rest,\n next.length > 0\n ? msg(\"meetings.settings.meetingsListenForTheseWords\")\n : msg(\"meetings.settings.meetingsListenForNoWords\"),\n );\n };\n const [confirmingOff, setConfirmingOff] = useState(false);\n const chooseVoiceprints = (next: boolean) => {\n if (next === voiceprints) return;\n if (!next) {\n setConfirmingOff(true);\n return;\n }\n void save(\n { ...current, voiceprints: true },\n msg(\"meetings.settings.peopleAreRecognizedByVoice\"),\n );\n };\n\n const liveTranscript = current.liveTranscript === true;\n const liveModel = models.liveModels[0] ?? null;\n const liveAvailable = models.liveModels.some((entry) => entry.available);\n const liveRestricted = liveTranscriptRestriction(models.liveModels, msg);\n const chooseLiveTranscript = (next: boolean) => {\n if (next === liveTranscript) return;\n const { liveTranscript: _previous, ...rest } = current;\n void save(\n next ? { ...rest, liveTranscript: true } : rest,\n next\n ? msg(\"meetings.settings.newMeetingsShowALive\")\n : msg(\"meetings.settings.newMeetingsDonTShow\"),\n );\n };\n\n // On unless turned off, so only `false` is ever saved.\n const autoSummary = current.autoSummary !== false;\n const chooseAutoSummary = (next: boolean) => {\n if (next === autoSummary) return;\n const { autoSummary: _previous, ...rest } = current;\n void save(\n next ? rest : { ...rest, autoSummary: false },\n next\n ? msg(\"meetings.settings.anAgentWritesTheNotes\")\n : msg(\"meetings.settings.meetingsNoLongerGetNotes\"),\n );\n };\n\n const retention = current.retention;\n const [pendingRetention, setPendingRetention] = useState<{\n next: RecordingRetention;\n success: string;\n warning: NonNullable<ReturnType<typeof retentionChangeWarning>>;\n } | null>(null);\n const saveRetention = (next: RecordingRetention, success: string) => {\n const { retention: _previous, ...rest } = current;\n const empty = next.audioDays === undefined && next.transcriptDays === undefined;\n return save(empty ? rest : { ...rest, retention: next }, success);\n };\n const chooseRetention = (field: \"audioDays\" | \"transcriptDays\", value: string) => {\n const days = value === KEEP ? undefined : Number(value);\n if (days === retention?.[field]) return;\n const next: RecordingRetention = {};\n const audioDays = field === \"audioDays\" ? days : retention?.audioDays;\n const transcriptDays = field === \"transcriptDays\" ? days : retention?.transcriptDays;\n if (transcriptDays !== undefined) next.transcriptDays = transcriptDays;\n // Audio never outlives its meeting; past that it simply goes with it.\n if (audioDays !== undefined && (transcriptDays === undefined || audioDays <= transcriptDays)) {\n next.audioDays = audioDays;\n }\n const success =\n field === \"audioDays\"\n ? days === undefined\n ? msg(\"meetings.settings.audioIsKeptAsLong\")\n : days === 0\n ? msg(\"meetings.settings.audioIsDeletedOnceThe\")\n : msg(\"meetings.settings.audioIsDeletedAfterRetentionperiodname\", {\n retentionPeriodName: retentionPeriodName(days, msg),\n })\n : days === undefined\n ? msg(\"meetings.settings.meetingsAreKeptUntilSomeone\")\n : msg(\"meetings.settings.meetingsAreDeletedAfterRetentionperiodname\", {\n retentionPeriodName: retentionPeriodName(days, msg),\n });\n const warning = retentionChangeWarning(retention, next, msg);\n if (warning) {\n setPendingRetention({ next, success, warning });\n return;\n }\n void saveRetention(next, success);\n };\n const periodOptions = (\n periods: readonly number[],\n selected: number | undefined,\n keepLabel: string,\n limit: number | undefined,\n ): SelectOption[] => {\n const days = [...new Set([...periods, ...(selected === undefined ? [] : [selected])])].sort(\n (a, b) => a - b,\n );\n return [\n { value: KEEP, label: keepLabel },\n ...days.map((day) => {\n const tooLong = limit !== undefined && day > limit;\n return {\n value: String(day),\n label:\n day === 0\n ? msg(\"meetings.settings.deleteOnceTranscribed\")\n : retentionPeriodName(day, msg),\n disabled: tooLong,\n disabledReason: tooLong\n ? msg(\"meetings.settings.meetingsAreDeletedAfterRetentionperiodname\", {\n retentionPeriodName: retentionPeriodName(limit, msg),\n })\n : undefined,\n };\n }),\n ];\n };\n\n return (\n <Section\n title={msg(\"meetings.settings.meetings\")}\n description={msg(\"meetings.settings.defaultsForNewMeetingsAnd\")}\n >\n {personal ? null : (\n <SettingRow\n label={msg(\"meetings.settings.whoSeesNewMeetings\")}\n description={\n visibility === \"workspace\"\n ? msg(\"meetings.settings.everyoneInThisWorkspaceCan\")\n : msg(\"meetings.settings.onlyThePersonWhoRecorded\")\n }\n controlWidth=\"auto\"\n control={\n <SegmentedControl\n size=\"sm\"\n value={visibility}\n onValueChange={(next) => chooseVisibility(next as RecordingVisibility)}\n options={[\n { value: \"private\", label: msg(\"meetings.settings.onlyMe\") },\n { value: \"workspace\", label: msg(\"meetings.settings.workspace\") },\n ].map((option) => ({\n ...option,\n disabled: saving || !canManage,\n ...(reason ? { disabledReason: reason } : {}),\n }))}\n />\n }\n />\n )}\n <SettingRow\n label={msg(\"meetings.settings.transcriptionModel\")}\n description={\n models.pinned\n ? msg(\"meetings.settings.turnsAMeetingSAudioPinned\")\n : msg(\"meetings.settings.turnsAMeetingSAudio\")\n }\n controlWidth=\"select\"\n hint={\n noneAvailable ? (\n onConnectModels ? (\n <SettingRowLink onClick={onConnectModels}>\n {msg(\"meetings.settings.connectATranscriptionProviderTo\")}\n </SettingRowLink>\n ) : (\n msg(\"meetings.settings.anOrganizationAdminNeedsTo\")\n )\n ) : undefined\n }\n control={\n <NativeSelect\n aria-label={msg(\"meetings.settings.transcriptionModel\")}\n options={modelOptions}\n value={chosen}\n onValueChange={chooseModel}\n loading={models.loading && models.models.length === 0}\n disabled={saving || !canManage || models.pinned}\n {...(models.pinned\n ? { disabledReason: msg(\"meetings.settings.thisDeploymentUsesOneModel\") }\n : reason\n ? { disabledReason: reason }\n : {})}\n />\n }\n />\n <SettingRow\n label={msg(\"meetings.settings.meetingLanguage\")}\n description={msg(\"meetings.settings.newMeetingsAreTranscribedIn2\")}\n controlWidth=\"select\"\n control={\n <NativeSelect\n aria-label={msg(\"meetings.settings.meetingLanguage\")}\n options={meetingLanguageOptions(language, undefined, msg)}\n value={language}\n onValueChange={chooseLanguage}\n disabled={saving || !canManage}\n {...(reason ? { disabledReason: reason } : {})}\n />\n }\n />\n <WordListRow\n words={keyterms}\n saving={saving}\n disabled={!canManage}\n disabledReason={reason}\n text={{\n label: msg(\"meetings.settings.wordsToListenFor\"),\n description: msg(\"meetings.settings.wordsToListenForDescription\"),\n placeholder: msg(\"meetings.settings.wordsToListenForPlaceholder\"),\n termTooLong: (term, max) =>\n msg(\"meetings.settings.wordTooLong\", { term, max: String(max) }),\n tooMany: (max) => msg(\"meetings.settings.tooManyWords\", { max: String(max) }),\n }}\n onChange={chooseKeyterms}\n />\n <SettingRow\n label={msg(\"meetings.settings.writeNotesAfterEachMeeting\")}\n description={msg(\"meetings.settings.whenATranscriptIsReady\")}\n control={\n <Switch\n aria-label={msg(\"meetings.settings.writeNotesAfterEachMeeting\")}\n checked={autoSummary}\n pending={saving}\n disabled={!canManage}\n {...(reason ? { disabledReason: reason } : {})}\n onCheckedChange={chooseAutoSummary}\n />\n }\n />\n {liveModel ? (\n <SettingRow\n label={msg(\"meetings.settings.liveTranscript\")}\n description={\n liveRestricted ??\n msg(\"meetings.settings.showsWhatSSaidWhile\", {\n value:\n liveModel.usdPerHour !== null\n ? msg(\"meetings.settings.providernameChargesAboutValuePer\", {\n providerName: liveModel.providerName,\n value: liveModel.usdPerHour.toFixed(2),\n })\n : \"\",\n })\n }\n hint={\n !models.loading && !liveAvailable && !liveRestricted ? (\n onConnectModels ? (\n <SettingRowLink onClick={onConnectModels}>\n {msg(\"meetings.settings.connectProvidernameToShowA\", {\n providerName: liveModel.providerName,\n })}\n </SettingRowLink>\n ) : (\n msg(\"meetings.settings.anOrganizationAdminNeedsTo2\", {\n providerName: liveModel.providerName,\n })\n )\n ) : undefined\n }\n control={\n <Switch\n aria-label={msg(\"meetings.settings.liveTranscript\")}\n checked={liveTranscript && !liveRestricted}\n pending={saving}\n disabled={!canManage || liveRestricted !== null}\n // The description already says \"Not supported in EU\".\n {...(!liveRestricted && reason ? { disabledReason: reason } : {})}\n onCheckedChange={chooseLiveTranscript}\n />\n }\n />\n ) : null}\n <SettingRow\n label={msg(\"meetings.settings.recognizePeopleByVoice\")}\n description={\n voiceprints\n ? msg(\"meetings.settings.suggestsNamesForSpeakersIt\")\n : msg(\"meetings.settings.suggestsNamesForSpeakersIt2\")\n }\n control={\n <Switch\n aria-label={msg(\"meetings.settings.recognizePeopleByVoice\")}\n checked={voiceprints}\n pending={saving}\n disabled={!canManage}\n {...(reason ? { disabledReason: reason } : {})}\n onCheckedChange={chooseVoiceprints}\n />\n }\n />\n {voiceprints ? (\n <VoiceRows\n workspaceId={workspaceId}\n viewer={viewer}\n {...(recordings ? { recordings } : {})}\n />\n ) : null}\n <SettingRow\n label={msg(\"meetings.settings.keepMeetings\")}\n description={msg(\"meetings.settings.countedFromWhenAMeeting\")}\n controlWidth=\"select\"\n control={\n <NativeSelect\n aria-label={msg(\"meetings.settings.keepMeetings\")}\n options={periodOptions(\n MEETING_PERIODS,\n retention?.transcriptDays,\n msg(\"meetings.settings.untilSomeoneDeletesThem\"),\n undefined,\n )}\n value={\n retention?.transcriptDays === undefined ? KEEP : String(retention.transcriptDays)\n }\n onValueChange={(value) => chooseRetention(\"transcriptDays\", value)}\n disabled={saving || !canManage}\n {...(reason ? { disabledReason: reason } : {})}\n />\n }\n />\n <SettingRow\n label={msg(\"meetings.settings.keepAudio\")}\n description={msg(\"meetings.settings.deletingTheAudioKeepsThe\")}\n controlWidth=\"select\"\n control={\n <NativeSelect\n aria-label={msg(\"meetings.settings.keepAudio\")}\n options={periodOptions(\n AUDIO_PERIODS,\n retention?.audioDays,\n msg(\"meetings.settings.asLongAsTheMeeting\"),\n retention?.transcriptDays,\n )}\n value={retention?.audioDays === undefined ? KEEP : String(retention.audioDays)}\n onValueChange={(value) => chooseRetention(\"audioDays\", value)}\n disabled={saving || !canManage}\n {...(reason ? { disabledReason: reason } : {})}\n />\n }\n />\n <ConfirmDialog\n open={pendingRetention !== null}\n onOpenChange={(open) => {\n if (!open) setPendingRetention(null);\n }}\n title={pendingRetention?.warning.title ?? \"\"}\n description={pendingRetention?.warning.description ?? \"\"}\n confirmLabel={pendingRetention?.warning.confirmLabel ?? \"\"}\n pendingLabel={msg(\"meetings.settings.saving\")}\n onConfirm={async () => {\n if (!pendingRetention) return false;\n return await saveRetention(pendingRetention.next, pendingRetention.success);\n }}\n />\n <ConfirmDialog\n open={confirmingOff}\n onOpenChange={setConfirmingOff}\n title={msg(\"meetings.settings.stopRecognizingPeopleByVoice\")}\n description={msg(\"meetings.settings.everyVoiceRememberedInThis\")}\n confirmLabel={msg(\"meetings.settings.turnOffAndForgetVoices\")}\n pendingLabel={msg(\"meetings.settings.forgetting\")}\n onConfirm={async () => {\n const { voiceprints: _previous, ...rest } = current;\n return await save(rest, msg(\"meetings.settings.voicesForgottenPeopleArenT\"));\n }}\n />\n </Section>\n );\n}\n\n/**\n * \"Your voice\": each member decides for themselves. Agreeing lets Opengeni\n * learn the voice from meetings where they're named as a speaker.\n */\nfunction VoiceRows({\n workspaceId,\n viewer,\n recordings,\n}: {\n workspaceId: string;\n viewer: MeetingSettingsViewer;\n recordings?: RecordingsClientOverride[\"recordings\"];\n}) {\n const msg = useOpenGeniText();\n const people = useRecordingPeople({ workspaceId, ...(recordings ? { recordings } : {}) });\n const [busy, setBusy] = useState(false);\n const me: RecordingPerson | null =\n people.people.find((person) => person.memberSubjectId === viewer.subjectId) ?? null;\n const voice = me?.voice ?? null;\n\n async function run(work: () => Promise<unknown>, success: string, failure: string) {\n setBusy(true);\n try {\n await work();\n toast.success(success);\n } catch (error) {\n toast.error(failure, {\n description: error instanceof Error ? userErrorText(error) : undefined,\n });\n } finally {\n setBusy(false);\n }\n }\n\n const remember = () =>\n void run(\n async () => {\n const person =\n me ??\n (await people.create({ displayName: viewer.name, memberSubjectId: viewer.subjectId }));\n await people.rememberVoice(person.id, \"self\");\n },\n msg(\"meetings.settings.yourVoiceWillBeRemembered\"),\n msg(\"meetings.settings.couldnTRememberYourVoice\"),\n );\n const forget = () =>\n void run(\n async () => {\n if (me) await people.forgetVoice(me.id);\n },\n msg(\"meetings.settings.yourVoiceIsForgotten\"),\n msg(\"meetings.settings.couldnTForgetYourVoice\"),\n );\n\n const others = people.people\n .filter((person) => person.voice && person.id !== me?.id)\n .sort((left, right) => left.displayName.localeCompare(right.displayName));\n const forgetOther = (person: RecordingPerson) =>\n void run(\n async () => await people.forgetVoice(person.id),\n msg(\"meetings.settings.displaynameSVoiceIsForgotten\", { displayName: person.displayName }),\n msg(\"meetings.settings.couldnTForgetThisVoice\"),\n );\n\n return (\n <>\n <SettingRow\n label={msg(\"meetings.settings.yourVoice\")}\n description={\n voice\n ? voice.learned\n ? msg(\"meetings.settings.rememberedMeetingsSuggestYourName\")\n : msg(\"meetings.settings.youAgreedOpengeniLearnsYour\")\n : msg(\"meetings.settings.letsMeetingsSuggestYourName\")\n }\n controlWidth=\"auto\"\n control={\n voice ? (\n <Button type=\"button\" size=\"sm\" variant=\"outline\" disabled={busy} onClick={forget}>\n {msg(\"meetings.settings.forgetMyVoice\")}\n </Button>\n ) : (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n disabled={busy || people.loading}\n onClick={remember}\n >\n {msg(\"meetings.settings.rememberMyVoice\")}\n </Button>\n )\n }\n />\n <SettingRow\n label={msg(\"meetings.settings.rememberedVoices\")}\n description={\n others.length === 0\n ? msg(\"meetings.settings.nobodyElseYetPeopleCan\")\n : msg(\"meetings.settings.peopleWhoseVoicesSuggestNames\")\n }\n controlWidth=\"auto\"\n />\n {others.length > 0 ? (\n <ul aria-label={msg(\"meetings.settings.rememberedVoices\")} className=\"grid gap-1 pb-2\">\n {others.map((person) => (\n <li key={person.id} className=\"flex min-w-0 items-center gap-3 py-1\">\n <span className=\"grid min-w-0 flex-1\">\n <span className=\"truncate text-sm leading-5 text-fg\">{person.displayName}</span>\n <span className=\"truncate text-xs leading-4 text-fg-muted\">\n {person.voice?.consent === \"self\"\n ? person.voice?.learned\n ? msg(\"meetings.settings.agreedForThemselves\")\n : msg(\"meetings.settings.agreedForThemselvesNotHeard\")\n : person.voice?.learned\n ? msg(\"meetings.settings.someoneConfirmedTheyAgreed\")\n : msg(\"meetings.settings.someoneConfirmedTheyAgreedNot\")}\n </span>\n </span>\n {person.memberSubjectId ? (\n <span className=\"shrink-0 text-xs leading-4 text-fg-muted\">\n {msg(\"meetings.settings.onlyTheyCanForgetIt\")}\n </span>\n ) : (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n disabled={busy}\n aria-label={msg(\"meetings.settings.forgetDisplaynameSVoice\", {\n displayName: person.displayName,\n })}\n onClick={() => forgetOther(person)}\n >\n {msg(\"meetings.settings.forget\")}\n </Button>\n )}\n </li>\n ))}\n </ul>\n ) : null}\n </>\n );\n}\n\nexport function MeetingDefaultsView(props: ComponentProps<typeof MeetingDefaultsViewContent>) {\n return (\n <MeetingsOverlayScope>\n <MeetingDefaultsViewContent {...props} />\n </MeetingsOverlayScope>\n );\n}\n"],"mappings":"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","names":["useEffect","useId","useMemo","useRef","useState","ChevronDownIcon","PencilIcon","toast","useEffect","useMemo","useRef","useState","useRef","useState","Fragment","jsx","useState","useRef","Fragment","jsx","jsxs","defaultText","useMemo","useRef","useState","useEffect","jsxs","jsx","Fragment","defaultText","Fragment","jsx","jsxs","defaultText","useState","useEffect","useRef","useId","toast","PencilIcon","useMemo","ChevronDownIcon","useCallback","useEffect","useMemo","useRef","useState","AudioLinesIcon","toast","jsx","toast","Fragment","jsx","jsxs","useState","useEffect","useCallback","useMemo","useRef","AudioLinesIcon","useCallback","useEffect","useMemo","useRef","useState","AudioLinesIcon","CheckIcon","ChevronDownIcon","LoaderCircleIcon","LockIcon","PencilIcon","Trash2Icon","toast","useCallback","useEffect","useRef","useState","PauseIcon","PlayIcon","jsx","jsxs","MeetingPlayer","useRef","useState","useCallback","useEffect","PauseIcon","PlayIcon","useEffect","useId","useRef","useState","toast","useEffect","useState","jsx","jsx","jsxs","useId","useRef","useState","toast","useEffect","Fragment","jsx","jsxs","defaultText","useEffect","useId","useMemo","useRef","useState","CheckIcon","LoaderCircleIcon","PencilIcon","toast","Fragment","jsx","jsxs","useState","PencilIcon","useRef","useEffect","toast","CheckIcon","useId","useMemo","LoaderCircleIcon","Fragment","jsx","jsxs","defaultText","errorText","useState","useMemo","useRef","useEffect","useCallback","LockIcon","ChevronDownIcon","CheckIcon","LoaderCircleIcon","toast","AudioLinesIcon","PencilIcon","Trash2Icon","useState","toast","Fragment","jsx","jsxs","defaultText","useState","toast"]}
|
|
1
|
+
{"version":3,"sources":["../src/meetings/recorder-panel.tsx","../src/meetings/live-transcript.tsx","../src/meetings/meeting-transcript.tsx","../src/meetings/overlay-scope.tsx","../src/meetings/meetings-list-page.tsx","../src/meetings/delete-meeting-dialog.tsx","../src/meetings/meeting-detail-page.tsx","../src/meetings/meeting-player.tsx","../src/meetings/meeting-ask.tsx","../src/meetings/sticky-bar-edge.tsx","../src/meetings/meeting-mentions.tsx","../src/meetings/meeting-notes.tsx","../src/meetings/meeting-settings.tsx"],"sourcesContent":["/**\n * The recorder on the Meetings page. Idle, it is one row: a title, whether to\n * include the other people (other apps' audio in the desktop app, a tab's audio\n * in a browser), and Start recording. Live, the same panel shows the\n * clock, a level meter per track, Pause and Stop, and where the audio is (on\n * this device, uploading, or waiting for the connection).\n */\nimport { useOpenGeniText, createOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\nimport {\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n type ComponentProps,\n} from \"react\";\nimport {\n ChevronDownIcon,\n CircleIcon,\n InfoIcon,\n LanguagesIcon,\n MicIcon,\n NotebookPenIcon,\n PauseIcon,\n PencilIcon,\n PlayIcon,\n SquareIcon,\n} from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\n\nimport { Button } from \"../ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuNote,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"../ui/dropdown-menu\";\nimport { Checkbox } from \"../ui/field\";\nimport { Input } from \"../ui/input\";\nimport { Notice } from \"../ui/notice\";\nimport { cn } from \"../app/lib/utils\";\n\nimport { formatClock, ownerLiveLaneName } from \"../recordings\";\nimport type { MeetingRecorder, MeetingStartRequest } from \"./recorder-context\";\nimport { canStartRecording } from \"./recorder-state\";\nimport { LiveTranscript, liveStatus, type LiveTranscriptLine } from \"./live-transcript\";\nimport { DETECT_LANGUAGE, meetingLanguageOptions } from \"./meeting-languages\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\n\nconst defaultText = createOpenGeniText();\n\ntype RecorderError = NonNullable<MeetingRecorder[\"error\"]>;\n\n/** What went wrong and what to do, in the browser's terms. */\nexport function recorderErrorText(\n error: RecorderError,\n systemAudioKind: MeetingRecorder[\"systemAudioKind\"] = \"display\",\n msg: OpenGeniText = defaultText,\n): { title: string; body: string } {\n if (systemAudioKind === \"desktop\" && error.code === \"system_audio_unavailable\") {\n return desktopSystemAudioErrorText(error.reason, msg);\n }\n switch (error.code) {\n case \"microphone_denied\":\n return {\n title: msg(\"meetings.recorderPanel.microphoneBlocked\"),\n body:\n systemAudioKind === \"desktop\"\n ? msg(\"meetings.recorderPanel.allowThisAppToUse\")\n : msg(\"meetings.recorderPanel.allowMicrophoneAccessForThis\"),\n };\n case \"microphone_unavailable\":\n return {\n title: msg(\"meetings.recorderPanel.noMicrophoneFound\"),\n body: msg(\"meetings.recorderPanel.connectAMicrophoneOrCheck\"),\n };\n case \"system_audio_not_shared\":\n return {\n title: msg(\"meetings.recorderPanel.theTabSAudioWasn\"),\n body: msg(\"meetings.recorderPanel.whenYourBrowserAsksWhat\"),\n };\n case \"system_audio_unavailable\":\n return {\n title: msg(\"meetings.recorderPanel.canTRecordATab\"),\n body: msg(\"meetings.recorderPanel.thisBrowserCanTShare\"),\n };\n case \"unsupported\":\n return {\n title: msg(\"meetings.recorderPanel.thisBrowserCanTRecord\"),\n body: msg(\"meetings.recorderPanel.useACurrentVersionOf\"),\n };\n case \"upload_failed\":\n return {\n title: msg(\"meetings.recorderPanel.uploadStopped\"),\n body: msg(\"meetings.recorderPanel.uploadfailurereasonTheRecordingIsSaved\", {\n uploadFailureReason: uploadFailureReason(error.message, msg),\n }),\n };\n default:\n return { title: msg(\"meetings.recorderPanel.recordingStopped\"), body: error.message };\n }\n}\n\n/** Why the desktop app couldn't record computer audio, and what to do on this computer. */\nfunction desktopSystemAudioErrorText(\n reason: RecorderError[\"reason\"],\n msg: OpenGeniText,\n): { title: string; body: string } {\n const title = msg(\"meetings.recorderPanel.canTRecordComputerAudio\");\n switch (reason) {\n case \"permission_denied\":\n return {\n title: msg(\"meetings.recorderPanel.computerAudioIsnTAllowed\"),\n body: msg(\"meetings.recorderPanel.allowThisAppToRecordComputerAudio\"),\n };\n case \"sound_server_unavailable\":\n return { title, body: msg(\"meetings.recorderPanel.noSoundServerIsRunning\") };\n case \"unavailable\":\n return { title, body: msg(\"meetings.recorderPanel.thisComputerCanTRecordItsOwnAudio\") };\n default:\n return { title, body: msg(\"meetings.recorderPanel.computerAudioDidnTStart\") };\n }\n}\n\n/** Why the server refused the audio, as a sentence; the server's own words when it's not a known case. */\nexport function uploadFailureReason(message: string, msg: OpenGeniText = defaultText): string {\n const text = message.trim();\n if (/not.?found|\\b404\\b/i.test(text)) {\n return msg(\"meetings.recorderPanel.theMeetingWasDeletedOr\");\n }\n if (/forbidden|permission|\\b403\\b/i.test(text)) {\n return msg(\"meetings.recorderPanel.youNoLongerHavePermission\");\n }\n if (/too large|\\b413\\b/i.test(text)) return msg(\"meetings.recorderPanel.aPieceOfTheAudio\");\n if (/usage allowance|\\b402\\b/i.test(text)) {\n return msg(\"meetings.recorderPanel.theUsageAllowanceIsUsed\");\n }\n if (!text) return msg(\"meetings.recorderPanel.theServerRefusedTheAudio\");\n return msg(\"meetings.recorderPanel.theServerRefusedTheAudio2\", {\n value: text.replace(/[.\\s]+$/, \"\"),\n });\n}\n\n/** Where the audio is right now, in one short line. */\nexport function uploadLine(\n recorder: MeetingRecorder,\n online: boolean,\n msg: OpenGeniText = defaultText,\n): string | null {\n const upload = recorder.upload;\n const capturing = recorder.state === \"recording\" || recorder.state === \"paused\";\n if (upload?.failed)\n return msg(\"meetings.recorderPanel.uploadFailedMessage\", { message: upload.failed.message });\n if (upload?.finalized) return msg(\"meetings.recorderPanel.uploaded\");\n if (upload?.discarded) return msg(\"meetings.recorderPanel.nothingWasRecordedSoNo\");\n if (!online || upload?.retryingAfterError) {\n return capturing\n ? msg(\"meetings.recorderPanel.notUploadingNoConnectionRecording\")\n : msg(\"meetings.recorderPanel.notUploadingNoConnectionThe\");\n }\n if (recorder.state === \"paused\")\n return msg(\"meetings.recorderPanel.nothingIsRecordedWhilePaused\");\n if (capturing) {\n // In a browser, closing the tab ends the recording; an app keeps recording.\n return recorder.systemAudioKind === \"desktop\"\n ? capturingWhat(recorder, msg)\n : msg(\"meetings.recorderPanel.capturingwhatValue\", {\n capturingWhat: capturingWhat(recorder, msg),\n value: msg(\"meetings.recorderPanel.youCanUseOtherPages\"),\n });\n }\n if (!upload || recorder.state === \"starting\") return null;\n // After Stop: the audio uploaded while it recorded, so usually only its end\n // is left; after a dropped connection it can be more.\n return msg(\"meetings.recorderPanel.savingTheRestOfTheAudio\");\n}\n\n/** What this recording captures, as a sentence. */\nfunction capturingWhat(recorder: MeetingRecorder, msg: OpenGeniText = defaultText): string {\n const sources = new Set(recorder.tracks.map((track) => track.source));\n const system = sources.has(\"system\");\n if (!sources.has(\"microphone\")) {\n return system\n ? recorder.systemAudioKind === \"desktop\"\n ? msg(\"meetings.recorderPanel.recordingYourComputerSAudio\")\n : msg(\"meetings.recorderPanel.recordingTheTabSAudio\")\n : msg(\"meetings.recorderPanel.recording\");\n }\n return system\n ? recorder.systemAudioKind === \"desktop\"\n ? msg(\"meetings.recorderPanel.recordingYourMicrophoneAndComputerAudio\")\n : msg(\"meetings.recorderPanel.recordingYourMicrophoneAndTabAudio\")\n : msg(\"meetings.recorderPanel.recordingYourMicrophoneOnly\");\n}\n\n/** True while audio is waiting on this device because the connection is down. */\nexport function uploadStalled(recorder: MeetingRecorder, online: boolean): boolean {\n const upload = recorder.upload;\n if (upload?.failed || upload?.finalized || upload?.discarded) return false;\n return !online || Boolean(upload?.retryingAfterError);\n}\n\n/** Whether the browser says it's online, kept current. */\nexport function useOnline(): boolean {\n const [online, setOnline] = useState(() =>\n typeof navigator === \"undefined\" ? true : navigator.onLine,\n );\n useEffect(() => {\n const update = () => setOnline(navigator.onLine);\n window.addEventListener(\"online\", update);\n window.addEventListener(\"offline\", update);\n return () => {\n window.removeEventListener(\"online\", update);\n window.removeEventListener(\"offline\", update);\n };\n }, []);\n return online;\n}\n\n/** A level bar fed from the analyser every frame, without re-rendering React. */\nfunction LevelMeter({\n recorder,\n trackNumber,\n label,\n paused,\n}: {\n recorder: MeetingRecorder;\n trackNumber: number;\n label: string;\n paused: boolean;\n}) {\n const barRef = useRef<HTMLSpanElement>(null);\n const levels = recorder.levels;\n useEffect(() => {\n let frame = 0;\n let smoothed = 0;\n const tick = () => {\n const level = paused ? 0 : (levels()[trackNumber] ?? 0);\n // Fast attack, slow release, so speech reads as steady movement.\n smoothed = level > smoothed ? level : smoothed * 0.88 + level * 0.12;\n if (barRef.current) barRef.current.style.transform = `scaleX(${Math.max(0.02, smoothed)})`;\n frame = requestAnimationFrame(tick);\n };\n frame = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(frame);\n }, [levels, trackNumber, paused]);\n return (\n // Label and bar are cells of the parent grid, so every label fits its\n // column and the bars line up.\n <div className=\"contents\">\n <span className=\"min-w-0 max-w-44 truncate text-xs leading-4 text-fg-muted\" title={label}>\n {label}\n </span>\n <span aria-hidden=\"true\" className=\"relative h-1.5 overflow-hidden rounded-full bg-surface-2\">\n <span\n ref={barRef}\n className=\"absolute inset-0 origin-left rounded-full bg-status-idle transition-transform duration-75 motion-reduce:transition-none\"\n style={{ transform: \"scaleX(0.02)\" }}\n />\n </span>\n </div>\n );\n}\n\nfunction trackLabel(\n source: string,\n systemAudioKind: MeetingRecorder[\"systemAudioKind\"],\n msg: OpenGeniText = defaultText,\n): string {\n if (source === \"microphone\") return msg(\"meetings.recorderPanel.microphone\");\n if (source === \"system\")\n return systemAudioKind === \"desktop\"\n ? msg(\"meetings.recorderPanel.computerAudio\")\n : msg(\"meetings.recorderPanel.tabAudio\");\n return msg(\"meetings.recorderPanel.audio\");\n}\n\n/**\n * Who a track's live text is from. Beside computer or tab audio the\n * microphone is the person recording (`ownerName`, else \"You\") and the other\n * track is \"Others\". A microphone alone may pick up a whole room, so it is\n * named like its level meter.\n */\nexport function liveSpeakerName(\n recorder: Pick<MeetingRecorder, \"tracks\" | \"systemAudioKind\">,\n trackNumber: number,\n msg: OpenGeniText = defaultText,\n ownerName?: string | null,\n): string {\n const owned = ownerLiveLaneName(\n recorder.tracks,\n trackNumber,\n ownerName?.trim() || msg(\"meetings.liveTranscript.you\"),\n msg,\n );\n if (owned) return owned;\n const source = recorder.tracks.find((track) => track.trackNumber === trackNumber)?.source;\n return trackLabel(source ?? \"\", recorder.systemAudioKind, msg);\n}\n\n/** The live text the recorder has heard, as lines for {@link LiveTranscript}. */\nexport function recorderLiveLines(recorder: Pick<MeetingRecorder, \"live\">): LiveTranscriptLine[] {\n return (recorder.live ?? []).flatMap((track) => track.segments);\n}\n\n/** Why live text stopped, in the recorder's terms, from the first track's reason. */\nexport function liveUnavailableText(\n tracks: readonly { error: { code: string; message: string } | null }[],\n msg: OpenGeniText = defaultText,\n): string {\n const code = tracks.find((track) => track.error)?.error?.code;\n const reason =\n code === \"quota_exceeded\"\n ? msg(\"meetings.recorderPanel.theLiveTranscriptionAccountHas\")\n : code === \"auth_error\"\n ? msg(\"meetings.recorderPanel.theLiveTranscriptionProviderRefused\")\n : code === \"credential_unavailable\"\n ? msg(\"meetings.recorderPanel.noLiveTranscriptionProviderIs\")\n : code === \"rate_limited\" || code === \"resource_exhausted\" || code === \"queue_overflow\"\n ? msg(\"meetings.recorderPanel.theLiveTranscriptionProviderIs\")\n : null;\n return msg(\"meetings.recorderPanel.liveTextIsnTAvailable\", { value: reason ? ` ${reason}` : \"\" });\n}\n\n/** The meeting's name while it records, and renaming it without stopping. */\nfunction RecordingTitle({ recorder }: { recorder: MeetingRecorder }) {\n const msg = useOpenGeniText();\n const inputId = useId();\n const [editing, setEditing] = useState(false);\n const [draft, setDraft] = useState(\"\");\n const [saving, setSaving] = useState(false);\n const title = recorder.title?.trim() || null;\n if (editing) {\n const save = async () => {\n const next = draft.trim();\n if (!next || next === title) {\n setEditing(false);\n return;\n }\n setSaving(true);\n try {\n await recorder.rename(next);\n setEditing(false);\n } catch (error) {\n toast.error(msg(\"meetings.recorderPanel.couldnTRenameThisMeeting\"), {\n description: error instanceof Error ? userErrorText(error) : undefined,\n });\n } finally {\n setSaving(false);\n }\n };\n return (\n <form\n className=\"mb-4 flex items-center gap-2 max-sm:flex-wrap\"\n onSubmit={(event) => {\n event.preventDefault();\n void save();\n }}\n >\n <label htmlFor={inputId} className=\"sr-only\">\n {msg(\"meetings.recorderPanel.meetingTitle\")}\n </label>\n <Input\n id={inputId}\n autoFocus\n value={draft}\n maxLength={300}\n placeholder={msg(\"meetings.recorderPanel.nameThisMeeting\")}\n disabled={saving}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") setEditing(false);\n }}\n className=\"h-9 min-w-0 flex-1 max-sm:basis-full\"\n />\n <Button type=\"submit\" size=\"sm\" disabled={saving} className=\"pointer-coarse:h-11\">\n {saving ? msg(\"meetings.recorderPanel.saving\") : msg(\"meetings.recorderPanel.save\")}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n disabled={saving}\n onClick={() => setEditing(false)}\n className=\"pointer-coarse:h-11\"\n >\n {msg(\"meetings.recorderPanel.cancel\")}\n </Button>\n </form>\n );\n }\n return (\n <div className=\"mb-4 flex min-w-0 items-center gap-1\">\n <p\n className={cn(\n \"min-w-0 truncate text-sm leading-5 font-medium\",\n title ? \"text-fg\" : \"text-fg-muted\",\n )}\n >\n {title ?? msg(\"meetings.recorderPanel.namedForYou\")}\n </p>\n <Button\n type=\"button\"\n size=\"xs\"\n variant=\"ghost\"\n onClick={() => {\n setDraft(title ?? \"\");\n setEditing(true);\n }}\n className=\"shrink-0 text-fg-label pointer-coarse:h-11\"\n >\n <PencilIcon aria-hidden=\"true\" />\n {title ? msg(\"meetings.recorderPanel.rename\") : msg(\"meetings.recorderPanel.nameIt\")}\n </Button>\n </div>\n );\n}\n\nfunction RecorderLiveTranscript({\n recorder,\n viewerName,\n}: {\n recorder: MeetingRecorder;\n viewerName: string | null;\n}) {\n const msg = useOpenGeniText();\n const live = recorder.live;\n const lines = useMemo(() => recorderLiveLines({ live: live ?? null }), [live]);\n if (!live || live.length === 0) return null;\n const status = liveStatus(live, msg);\n if (lines.length === 0 && live.every((track) => track.state === \"unavailable\")) {\n // Nothing to read, so no empty box: one line says it and that nothing is lost.\n return (\n <p\n className=\"mt-3 flex items-start gap-2 rounded-[10px] border border-border bg-surface-2/60 px-3 py-2 text-xs leading-4.5 text-fg-label\"\n aria-live=\"polite\"\n >\n <InfoIcon aria-hidden=\"true\" className=\"mt-0.5 size-3.5 shrink-0 text-fg-muted\" />\n {liveUnavailableText(live, msg)}\n </p>\n );\n }\n return (\n <LiveTranscript\n className=\"mt-4 border-t border-border pt-4\"\n lines={lines}\n partials={live.map((track) => ({ trackNumber: track.trackNumber, text: track.partial }))}\n tracks={recorder.tracks}\n speakerName={(trackNumber) => liveSpeakerName(recorder, trackNumber, msg, viewerName)}\n status={status}\n empty={\n recorder.state === \"paused\"\n ? msg(\"meetings.recorderPanel.pausedNothingIsHeardUntil\")\n : msg(\"meetings.recorderPanel.listeningWhatSSaidShows\")\n }\n />\n );\n}\n\n/** The pulsing dot, the state in a word and the clock of a recording under way. */\nfunction RecordingClock({ recorder, stalled }: { recorder: MeetingRecorder; stalled: boolean }) {\n const msg = useOpenGeniText();\n const paused = recorder.state === \"paused\";\n return (\n <div className=\"flex min-w-0 items-center gap-3\">\n <span className=\"relative flex size-3 shrink-0\" aria-hidden=\"true\">\n {!paused ? (\n <span\n className={cn(\n \"absolute inset-0 animate-ping rounded-full motion-reduce:animate-none\",\n stalled ? \"bg-status-waiting/60\" : \"bg-status-failed/60\",\n )}\n />\n ) : null}\n <span\n className={cn(\n \"relative size-3 rounded-full\",\n paused ? \"bg-fg-subtle\" : stalled ? \"bg-status-waiting\" : \"bg-status-failed\",\n )}\n />\n </span>\n <div className=\"min-w-0\">\n <p className=\"text-sm leading-5 font-medium text-fg\">\n {recorder.state === \"stopping\"\n ? msg(\"meetings.recorderPanel.finishing\")\n : paused\n ? msg(\"meetings.recorderPanel.paused\")\n : stalled\n ? msg(\"meetings.recorderPanel.recordingNotUploading\")\n : msg(\"meetings.recorderPanel.recording2\")}\n </p>\n <p\n className=\"text-2xl leading-8 font-semibold tracking-[-0.5px] text-fg tabular-nums\"\n role=\"timer\"\n aria-live=\"off\"\n >\n {formatClock(recorder.elapsedMilliseconds)}\n </p>\n </div>\n </div>\n );\n}\n\n/** Pause or Resume, and Stop. */\nfunction RecordingControls({\n recorder,\n onStopped,\n}: {\n recorder: MeetingRecorder;\n onStopped?: ((recordingId: string) => void) | undefined;\n}) {\n const msg = useOpenGeniText();\n const paused = recorder.state === \"paused\";\n const stopping = recorder.state === \"stopping\";\n const recordingId = recorder.recordingId;\n return (\n <>\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={stopping}\n onClick={() => (paused ? recorder.resume() : recorder.pause())}\n className=\"rounded-[10px] pointer-coarse:h-11 max-sm:flex-1\"\n >\n {paused ? <PlayIcon aria-hidden=\"true\" /> : <PauseIcon aria-hidden=\"true\" />}\n {paused ? msg(\"meetings.recorderPanel.resume\") : msg(\"meetings.recorderPanel.pause\")}\n </Button>\n <Button\n type=\"button\"\n disabled={stopping}\n onClick={() => {\n void recorder.stop().then(() => {\n if (recordingId) onStopped?.(recordingId);\n });\n }}\n className=\"rounded-[10px] pointer-coarse:h-11 max-sm:flex-1\"\n >\n <SquareIcon aria-hidden=\"true\" className=\"fill-current\" />\n {msg(\"meetings.recorderPanel.stop\")}\n </Button>\n </>\n );\n}\n\n/**\n * The recording on the meeting's own page while this device records it, so\n * taking notes there never hides that it is still recording or how to end it:\n * the state and clock with Pause and Stop. Says so only when the connection\n * keeps the audio on this device.\n */\nexport function RecordingBar({\n recorder,\n onStopped,\n}: {\n recorder: MeetingRecorder;\n /** After Stop, with the recording that stopped. */\n onStopped?: ((recordingId: string) => void) | undefined;\n}) {\n const msg = useOpenGeniText();\n const online = useOnline();\n const stalled = uploadStalled(recorder, online);\n return (\n <section\n aria-label={msg(\"meetings.recorderPanel.recording2\")}\n className=\"rounded-[14px] border border-border bg-surface px-5 py-4 shadow-[0_1px_2px_rgb(0_0_0/0.04)] max-sm:p-4\"\n >\n <div className=\"flex flex-wrap items-center justify-between gap-x-6 gap-y-3\">\n <RecordingClock recorder={recorder} stalled={stalled} />\n <div className=\"flex shrink-0 items-center gap-2 max-sm:w-full\">\n <RecordingControls recorder={recorder} onStopped={onStopped} />\n </div>\n </div>\n {stalled ? (\n <p className=\"mt-3 text-xs leading-4.5 font-medium text-fg-label\" aria-live=\"polite\">\n {uploadLine(recorder, online, msg)}\n </p>\n ) : null}\n </section>\n );\n}\n\nfunction RecorderPanelContent({\n recorder,\n onStopped,\n onOpenNotes,\n liveTranscript = null,\n defaultLanguage,\n autoStart = null,\n externalRef = null,\n notice = null,\n viewerName = null,\n}: {\n /** Null while the capture code loads. */\n recorder: MeetingRecorder | null;\n /** After Stop, with the recording to open. */\n onStopped?: ((recordingId: string) => void) | undefined;\n /** Opens the meeting being recorded, where its notepad is. */\n onOpenNotes?: ((recordingId: string) => void) | undefined;\n /** Offer the live transcript preview; null when the workspace has no live model. */\n liveTranscript?: { defaultOn: boolean; usdPerHour?: number | null } | null;\n /**\n * The workspace's meeting language; null detects it. Undefined while it\n * isn't known: a meeting started then names no language, and the server\n * uses the workspace's.\n */\n defaultLanguage?: string | null | undefined;\n /**\n * Start recording as soon as the recorder is ready, with this panel's\n * defaults, as a desktop call notification asked. `take` returns the\n * request once, so it starts one recording.\n */\n autoStart?: {\n pending: boolean;\n take: () => MeetingStartRequest | null;\n } | null;\n /** The host's own id for what new recordings belong to, such as a project. */\n externalRef?: string | null | undefined;\n /** A short line shown before every start, such as a reminder to tell the people present. */\n notice?: ReactNode;\n /** The person recording's name, for their microphone's live text beside computer or tab audio. */\n viewerName?: string | null | undefined;\n}) {\n const msg = useOpenGeniText();\n const titleId = useId();\n const tabAudioId = useId();\n const [title, setTitle] = useState(\"\");\n const [languageChoice, setLanguage] = useState<string | null>(null);\n const language = languageChoice ?? defaultLanguage ?? DETECT_LANGUAGE;\n const desktopAudio = recorder?.systemAudioKind === \"desktop\";\n // In the desktop app computer audio is on unless turned off; a browser's\n // share prompt is something to opt into.\n const [tabAudioChoice, setTabAudio] = useState<boolean | null>(null);\n const tabAudio = tabAudioChoice ?? desktopAudio;\n const [liveChoice, setLiveChoice] = useState<boolean | null>(null);\n const liveOn = liveTranscript ? (liveChoice ?? liveTranscript.defaultOn) : false;\n const [errorDismissed, setErrorDismissed] = useState(false);\n const online = useOnline();\n const state = recorder?.state ?? \"idle\";\n const live = state === \"recording\" || state === \"paused\" || state === \"stopping\";\n\n /**\n * `guess` is the app's name for the meeting, used only when nobody typed\n * one; `calendarEvent` the calendar event it is of, which names it.\n */\n const start = async (\n titleText: string = title,\n guess?: string,\n calendarEvent?: MeetingStartRequest[\"calendarEvent\"],\n ) => {\n if (!recorder) return;\n setErrorDismissed(false);\n const name = titleText.trim();\n const guessed = guess?.trim();\n await recorder.start({\n // Unnamed, Opengeni names it: after the calendar event at the time, or\n // from the conversation once its notes are written.\n ...(name ? { title: name } : guessed ? { title: guessed, titleSource: \"app\" as const } : {}),\n systemAudio: tabAudio,\n ...(liveOn ? { liveTranscript: true } : {}),\n ...(externalRef ? { externalRef } : {}),\n ...(calendarEvent ? { calendarEvent } : {}),\n // Names their microphone in the transcript when Opengeni has no name for them.\n ...(viewerName?.trim() ? { ownerName: viewerName } : {}),\n // Sent even when it's the workspace's, so this meeting keeps it.\n transcription:\n languageChoice === null && defaultLanguage === undefined\n ? {}\n : { language: language === DETECT_LANGUAGE ? null : language },\n });\n };\n // After an earlier recording stopped or failed too, as a click on Start would.\n const autoStartReady = Boolean(\n autoStart?.pending && recorder?.supported && canStartRecording(state),\n );\n const startRef = useRef(start);\n startRef.current = start;\n useEffect(() => {\n if (!autoStartReady) return;\n const request = autoStart?.take();\n if (!request) return;\n // The call app's name is a guess: a title already typed wins over it.\n if (request.titleSource === \"app\") {\n void startRef.current(undefined, request.title, request.calendarEvent);\n return;\n }\n // A start without a title (the Start recording key) keeps one already typed, as the button does.\n if (request.title) setTitle(request.title);\n void startRef.current(request.title || undefined);\n }, [autoStart, autoStartReady]);\n\n if (recorder && !recorder.supported) {\n return (\n <Notice tone=\"muted\" title={msg(\"meetings.recorderPanel.thisBrowserCanTRecord\")}>\n {msg(\"meetings.recorderPanel.useACurrentVersionOf2\")}\n </Notice>\n );\n }\n\n if (recorder && live) {\n const stalled = uploadStalled(recorder, online);\n const recordingId = recorder.recordingId;\n const line = uploadLine(recorder, online, msg);\n return (\n <section\n aria-label={msg(\"meetings.recorderPanel.recording2\")}\n className=\"rounded-[14px] border border-border bg-surface p-5 shadow-[0_1px_2px_rgb(0_0_0/0.04)] max-sm:p-4\"\n >\n <RecordingTitle recorder={recorder} />\n <div className=\"flex flex-wrap items-center gap-x-6 gap-y-4\">\n <RecordingClock recorder={recorder} stalled={stalled} />\n <div className=\"grid min-w-48 flex-1 grid-cols-[minmax(0,max-content)_minmax(4rem,1fr)] items-center gap-x-3 gap-y-2\">\n {recorder.tracks.map((track) => (\n <LevelMeter\n key={track.trackNumber}\n recorder={recorder}\n trackNumber={track.trackNumber}\n label={trackLabel(track.source, recorder.systemAudioKind, msg)}\n paused={state === \"paused\"}\n />\n ))}\n </div>\n <div className=\"flex shrink-0 items-center gap-2 max-sm:w-full\">\n {onOpenNotes && recordingId && recorder.upload?.created ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={() => onOpenNotes(recordingId)}\n className=\"rounded-[10px] pointer-coarse:h-11 max-sm:flex-1\"\n >\n <NotebookPenIcon aria-hidden=\"true\" />\n {msg(\"meetings.recorderPanel.takeNotes\")}\n </Button>\n ) : null}\n <RecordingControls recorder={recorder} onStopped={onStopped} />\n </div>\n </div>\n {line ? (\n <p\n className={cn(\n \"mt-3 text-xs leading-4.5\",\n stalled ? \"font-medium text-fg-label\" : \"text-fg-muted\",\n )}\n aria-live=\"polite\"\n >\n {line}\n </p>\n ) : null}\n <RecorderLiveTranscript recorder={recorder} viewerName={viewerName} />\n </section>\n );\n }\n\n const starting = state === \"starting\";\n const error = recorder?.error && !errorDismissed ? recorder.error : null;\n const startHint = recorderHint(\n {\n desktopAudio,\n starting,\n tabAudio,\n systemAudioSupported: Boolean(recorder?.systemAudioSupported),\n },\n msg,\n );\n return (\n <section aria-label={msg(\"meetings.recorderPanel.newRecording\")} className=\"grid gap-3\">\n <form\n className=\"flex items-center gap-3 rounded-[14px] border border-border bg-surface p-2 pl-4 shadow-[0_1px_2px_rgb(0_0_0/0.04)] max-sm:flex-col max-sm:items-stretch max-sm:gap-2 max-sm:p-3\"\n onSubmit={(event) => {\n event.preventDefault();\n void start();\n }}\n >\n <MicIcon aria-hidden=\"true\" className=\"size-4 shrink-0 text-fg-subtle max-sm:hidden\" />\n <label htmlFor={titleId} className=\"sr-only\">\n {msg(\"meetings.recorderPanel.meetingTitle\")}\n </label>\n <Input\n id={titleId}\n value={title}\n maxLength={300}\n onChange={(event) => setTitle(event.target.value)}\n placeholder={msg(\"meetings.recorderPanel.nameThisMeetingOptional\")}\n className=\"h-9 min-w-0 flex-1 border-0 bg-transparent px-0 shadow-none focus-visible:ring-0 max-sm:flex-none dark:bg-transparent\"\n disabled={starting}\n />\n {recorder?.systemAudioSupported ? (\n <label\n htmlFor={tabAudioId}\n className=\"flex shrink-0 cursor-pointer items-center gap-2 text-sm leading-5 text-fg-label select-none pointer-coarse:min-h-11 max-sm:self-start\"\n title={\n desktopAudio\n ? msg(\"meetings.recorderPanel.recordsTheOtherPeopleIn\")\n : msg(\"meetings.recorderPanel.recordsTheOtherPeopleIn2\")\n }\n >\n <Checkbox\n id={tabAudioId}\n checked={tabAudio}\n disabled={starting}\n onCheckedChange={setTabAudio}\n />\n {desktopAudio\n ? msg(\"meetings.recorderPanel.includeComputerAudio\")\n : msg(\"meetings.recorderPanel.includeATabSAudio\")}\n </label>\n ) : null}\n <RecorderOptions\n language={language}\n onLanguageChange={setLanguage}\n live={\n liveTranscript\n ? {\n on: liveOn,\n usdPerHour: liveTranscript.usdPerHour ?? null,\n onChange: setLiveChoice,\n }\n : null\n }\n disabled={starting}\n />\n <Button\n type=\"submit\"\n disabled={!recorder || starting}\n className=\"shrink-0 rounded-[10px] pointer-coarse:h-11 max-sm:w-full\"\n >\n <CircleIcon aria-hidden=\"true\" className=\"fill-status-failed text-status-failed\" />\n {starting\n ? msg(\"meetings.recorderPanel.starting\")\n : msg(\"meetings.recorderPanel.startRecording\")}\n </Button>\n </form>\n {error ? (\n <Notice\n tone=\"failed\"\n title={recorderErrorText(error, recorder?.systemAudioKind, msg).title}\n onDismiss={() => setErrorDismissed(true)}\n >\n {recorderErrorText(error, recorder?.systemAudioKind, msg).body}\n </Notice>\n ) : null}\n {notice ? <p className=\"px-1 text-sm leading-5 text-fg-label\">{notice}</p> : null}\n <p className=\"px-1 text-xs leading-4.5 text-fg-muted\" aria-live=\"polite\">\n {startHint}\n </p>\n </section>\n );\n}\n\n/**\n * The meeting's language and the live transcript: set once in Meetings\n * settings, so they wait in one small menu beside Start instead of crowding it.\n */\nexport function RecorderOptions({\n language,\n onLanguageChange,\n live,\n disabled,\n defaultOpen = false,\n}: {\n language: string;\n onLanguageChange: (language: string) => void;\n live: { on: boolean; usdPerHour: number | null; onChange: (on: boolean) => void } | null;\n disabled: boolean;\n /** Tests open it without a pointer. */\n defaultOpen?: boolean;\n}) {\n const msg = useOpenGeniText();\n const options = meetingLanguageOptions(\n language,\n msg(\"meetings.recorderPanel.detectLanguage\"),\n msg,\n );\n const current = options.find((option) => option.value === language)?.label ?? language;\n return (\n <DropdownMenu defaultOpen={defaultOpen}>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={disabled}\n aria-label={msg(\"meetings.recorderPanel.recordingOptionsLanguage\", { language: current })}\n className=\"shrink-0 rounded-[10px] text-fg-label pointer-coarse:h-11 max-sm:-ml-3 max-sm:self-start\"\n >\n <LanguagesIcon aria-hidden=\"true\" />\n {current}\n <ChevronDownIcon aria-hidden=\"true\" className=\"text-fg-subtle\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-64\">\n {/* The live transcript first, so it never hides below the languages. */}\n {live ? (\n <>\n <DropdownMenuCheckboxItem\n checked={live.on}\n onCheckedChange={(checked) => live.onChange(checked === true)}\n onSelect={(event) => event.preventDefault()}\n >\n {msg(\"meetings.recorderPanel.liveTranscript\")}\n </DropdownMenuCheckboxItem>\n <DropdownMenuNote>\n {[msg(\"meetings.recorderPanel.showsWhatSSaidAs\"), liveCostHint(live.usdPerHour, msg)]\n .filter(Boolean)\n .join(\" \")}\n </DropdownMenuNote>\n <DropdownMenuSeparator />\n </>\n ) : null}\n <DropdownMenuLabel>{msg(\"meetings.recorderPanel.meetingLanguage\")}</DropdownMenuLabel>\n <DropdownMenuRadioGroup value={language} onValueChange={onLanguageChange}>\n {options.map((option) => (\n <DropdownMenuRadioItem key={option.value} value={option.value}>\n {option.label}\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\n/**\n * What the live preview adds to the bill, where it's switched on; empty when\n * this workspace isn't charged by the hour for it.\n */\nexport function liveCostHint(usdPerHour: number | null, msg: OpenGeniText = defaultText): string {\n return usdPerHour !== null\n ? msg(\"meetings.recorderPanel.theLiveTranscriptAddsAbout\", { value: usdPerHour.toFixed(2) })\n : \"\";\n}\n\nfunction recorderHint(\n {\n desktopAudio,\n starting,\n tabAudio,\n systemAudioSupported,\n }: {\n desktopAudio: boolean;\n starting: boolean;\n tabAudio: boolean;\n systemAudioSupported: boolean;\n },\n msg: OpenGeniText = defaultText,\n): string {\n return desktopAudio\n ? starting\n ? msg(\"meetings.recorderPanel.startingAllowTheMicrophoneAnd\")\n : tabAudio\n ? msg(\"meetings.recorderPanel.recordsYourMicrophoneAndEverything\")\n : msg(\"meetings.recorderPanel.microphoneOnlySoPeopleOn\")\n : starting\n ? tabAudio\n ? msg(\"meetings.recorderPanel.startingAllowTheMicrophoneIf\")\n : msg(\"meetings.recorderPanel.startingAllowTheMicrophoneIf2\")\n : tabAudio\n ? msg(\"meetings.recorderPanel.yourBrowserAsksWhatTo\")\n : systemAudioSupported\n ? msg(\"meetings.recorderPanel.recordsYourMicrophoneForA\")\n : msg(\"meetings.recorderPanel.recordsYourMicrophoneTellEveryone\");\n}\n\nexport function RecorderPanel(props: ComponentProps<typeof RecorderPanelContent>) {\n return (\n <MeetingsOverlayScope>\n <RecorderPanelContent {...props} />\n </MeetingsOverlayScope>\n );\n}\n","/**\n * The live transcript preview: what is being said while a meeting is\n * recorded, one turn per stretch of speech on a track. It is a preview; the\n * meeting's real transcript (with speakers told apart) replaces it once the\n * recording is done.\n */\nimport { useOpenGeniText, createOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\nimport type { RecordingTrack } from \"@opengeni/contracts\";\nimport { useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { ArrowDownIcon } from \"lucide-react\";\n\nimport { Button } from \"../ui/button\";\nimport { cn } from \"../app/lib/utils\";\nimport {\n formatClock,\n groupLiveTurns,\n tidyLiveText,\n tidyPartialText,\n withoutLiveMicrophoneEchoes,\n type LiveTranscriptLine,\n} from \"../recordings\";\n\nimport { SpeakerDot } from \"./meeting-transcript\";\n\nconst defaultText = createOpenGeniText();\n\nexport { groupLiveTurns, tidyLiveText, tidyPartialText, type LiveTranscriptLine };\n\nconst NO_PARTIALS: readonly { trackNumber: number; text: string }[] = [];\nconst NO_TRACKS: readonly { trackNumber: number; source: RecordingTrack[\"source\"] }[] = [];\n\nexport function LiveTranscript({\n lines,\n partials = NO_PARTIALS,\n tracks = NO_TRACKS,\n speakerName,\n status,\n empty,\n heading = true,\n className,\n}: {\n lines: readonly LiveTranscriptLine[];\n /** Words still being heard per track, which may change. */\n partials?: readonly { trackNumber: number; text: string }[];\n /**\n * The recording's tracks. With computer or tab audio beside the\n * microphone, the microphone's echo of the others is left out.\n */\n tracks?: readonly { trackNumber: number; source: RecordingTrack[\"source\"] }[];\n speakerName: (trackNumber: number) => string;\n /** A short line about the connection, such as reconnecting. */\n status?: { text: string; tone: \"muted\" | \"waiting\" } | null;\n /** Shown before anything has been said. */\n empty: string;\n /** Show the \"Live transcript · preview\" heading; off where the page already has one. */\n heading?: boolean;\n className?: string;\n}) {\n const msg = useOpenGeniText();\n const turns = useMemo(\n () => groupLiveTurns(withoutLiveMicrophoneEchoes(lines, tracks)),\n [lines, tracks],\n );\n const heard = partials\n .map((partial) => ({ ...partial, text: tidyPartialText(partial.text) }))\n .filter((partial) => partial.text);\n // Words still being heard from whoever spoke last continue their turn.\n const lastTrack = turns.at(-1)?.trackNumber;\n const continuing = heard.find((partial) => partial.trackNumber === lastTrack) ?? null;\n const newTurns = heard.filter((partial) => partial !== continuing);\n const scrollRef = useRef<HTMLDivElement>(null);\n // Follow the newest words unless the reader scrolled up to reread.\n const following = useRef(true);\n const [scroll, setScroll] = useState({ above: false, behind: false });\n useEffect(() => {\n const element = scrollRef.current;\n if (!element) return;\n const onScroll = () => {\n const atEnd = element.scrollHeight - element.scrollTop - element.clientHeight < 24;\n following.current = atEnd;\n const above = element.scrollTop > 4;\n setScroll((previous) =>\n previous.above === above && previous.behind === !atEnd\n ? previous\n : { above, behind: !atEnd },\n );\n };\n element.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => element.removeEventListener(\"scroll\", onScroll);\n }, []);\n const content = `${turns.length}:${turns.at(-1)?.texts.length ?? 0}:${heard\n .map((partial) => partial.text.length)\n .join(\",\")}`;\n useLayoutEffect(() => {\n const element = scrollRef.current;\n if (!element) return;\n if (following.current) element.scrollTop = element.scrollHeight;\n const above = element.scrollTop > 4;\n setScroll((previous) => (previous.above === above ? previous : { ...previous, above }));\n }, [content]);\n const jumpToLatest = () => {\n const element = scrollRef.current;\n if (!element) return;\n following.current = true;\n element.scrollTop = element.scrollHeight;\n };\n\n const statusLine = status ? (\n status.tone === \"waiting\" ? (\n // A dropped connection is a state of the whole box, so it reads as a banner over it.\n <p\n className=\"flex items-start gap-2 rounded-[10px] border border-status-waiting/40 bg-status-waiting/10 px-3 py-2 text-xs leading-4.5 font-medium text-fg-label\"\n aria-live=\"polite\"\n >\n <span\n aria-hidden=\"true\"\n className=\"mt-1.5 inline-block size-1.5 shrink-0 animate-pulse rounded-full bg-status-waiting motion-reduce:animate-none\"\n />\n {status.text}\n </p>\n ) : (\n <p className=\"text-xs leading-4 text-fg-muted\" aria-live=\"polite\">\n {status.text}\n </p>\n )\n ) : null;\n\n return (\n <section\n aria-label={msg(\"meetings.liveTranscript.liveTranscript\")}\n className={cn(\"grid min-w-0 gap-2\", className)}\n >\n {heading ? (\n <>\n <div className=\"flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1\">\n <h3 className=\"text-xs leading-4 font-medium text-fg-label\">\n {msg(\"meetings.liveTranscript.liveTranscript\")}{\" \"}\n <span className=\"font-normal text-fg-muted\">\n {msg(\"meetings.liveTranscript.preview\")}\n </span>\n </h3>\n {status?.tone === \"muted\" ? statusLine : null}\n </div>\n {status?.tone === \"waiting\" ? statusLine : null}\n </>\n ) : (\n statusLine\n )}\n <div className=\"relative min-w-0 rounded-[10px] border border-border bg-surface-2/60\">\n <div\n ref={scrollRef}\n role=\"log\"\n aria-live=\"polite\"\n aria-label={msg(\"meetings.liveTranscript.liveTranscriptText\")}\n tabIndex={0}\n className={cn(\n \"max-h-64 min-h-16 overflow-y-auto rounded-[10px] px-3 py-2.5 focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-hidden\",\n // Older text above fades out, so a clipped first line reads as \"scroll up\".\n scroll.above && \"[mask-image:linear-gradient(to_bottom,transparent,black_2.5rem)]\",\n )}\n >\n {turns.length === 0 && heard.length === 0 ? (\n <p className=\"text-sm leading-5 text-fg-muted\">{empty}</p>\n ) : (\n <ol className=\"grid gap-3\">\n {turns.map((turn, index) => (\n <li key={turn.key} className=\"grid min-w-0 gap-0.5\">\n <div className=\"flex items-center gap-2\">\n <SpeakerDot slot={turn.trackNumber + 1} />\n <span className=\"text-xs leading-4 font-semibold text-fg\">\n {speakerName(turn.trackNumber)}\n </span>\n <span className=\"text-xs leading-4 text-fg-muted tabular-nums\">\n {formatClock(turn.startMilliseconds)}\n </span>\n </div>\n <p className=\"text-sm leading-5 text-pretty text-fg\">\n {tidyLiveText(turn.texts)}\n {continuing && index === turns.length - 1 ? (\n <span className=\"text-fg-label\"> {continuing.text}</span>\n ) : null}\n </p>\n </li>\n ))}\n {newTurns.map((partial) => (\n <li key={`partial:${partial.trackNumber}`} className=\"grid min-w-0 gap-0.5\">\n <div className=\"flex items-center gap-2\">\n <SpeakerDot slot={partial.trackNumber + 1} />\n <span className=\"text-xs leading-4 font-semibold text-fg\">\n {speakerName(partial.trackNumber)}\n </span>\n <span className=\"inline-flex items-center gap-1 text-xs leading-4 font-medium text-fg-label\">\n <span\n aria-hidden=\"true\"\n className=\"inline-block size-1.5 animate-pulse rounded-full bg-status-waiting motion-reduce:animate-none\"\n />\n {msg(\"meetings.liveTranscript.now\")}\n </span>\n </div>\n <p className=\"text-sm leading-5 text-fg-label\">{partial.text}</p>\n </li>\n ))}\n </ol>\n )}\n </div>\n {scroll.behind ? (\n <Button\n type=\"button\"\n size=\"xs\"\n variant=\"outline\"\n onClick={jumpToLatest}\n className=\"absolute right-3 bottom-2 rounded-full bg-surface shadow-[0_1px_2px_rgb(0_0_0/0.08)] pointer-coarse:h-11\"\n >\n <ArrowDownIcon aria-hidden=\"true\" />\n {msg(\"meetings.liveTranscript.latest\")}\n </Button>\n ) : null}\n </div>\n </section>\n );\n}\n\n/** The local recorder's live state as the panel's status line, or null when all is well. */\nexport function liveStatus(\n tracks: readonly { state: string; error: { message: string } | null }[],\n msg: OpenGeniText = defaultText,\n): { text: string; tone: \"muted\" | \"waiting\" } | null {\n if (tracks.length === 0) return null;\n if (tracks.every((track) => track.state === \"unavailable\")) {\n return {\n text: msg(\"meetings.liveTranscript.livePreviewUnavailableTheRecording\"),\n tone: \"muted\",\n };\n }\n if (tracks.some((track) => track.state === \"reconnecting\")) {\n return {\n text: msg(\"meetings.liveTranscript.reconnectingTheLiveTextThe\"),\n tone: \"waiting\",\n };\n }\n if (tracks.every((track) => track.state === \"connecting\")) {\n return { text: msg(\"meetings.liveTranscript.connecting\"), tone: \"muted\" };\n }\n return null;\n}\n","/**\n * The transcript as a person reads it: turns of one speaker, each a soft\n * bubble under the speaker's name in their colour, with its time and the line\n * playing now highlighted. A speaker's name opens \"Who is this?\" (someone from\n * the people directory, or a new name); a turn's pencil corrects its words and\n * its ⋯ menu moves it to another speaker. A name recognized by voice is marked\n * suggested until someone confirms or turns it down.\n */\nimport { useOpenGeniText, createOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\nimport {\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ComponentProps,\n type CSSProperties,\n} from \"react\";\nimport {\n AudioLinesIcon,\n CheckIcon,\n ChevronDownIcon,\n MoreHorizontalIcon,\n PencilIcon,\n UserIcon,\n UserPlusIcon,\n UsersIcon,\n XIcon,\n} from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\nimport type {\n RecordingPerson,\n RecordingSpeaker,\n RecordingTrack,\n RecordingTranscriptSegment,\n} from \"@opengeni/contracts\";\n\nimport { Button } from \"../ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"../ui/dropdown-menu\";\nimport { Field, FieldStack, TextArea, TextInput } from \"../ui/field\";\nimport { FormDialog } from \"../ui/form-dialog\";\nimport { cn } from \"../app/lib/utils\";\n\nimport {\n formatClock,\n groupTranscriptTurns,\n speakerColorSlots,\n speakerDisplayName,\n speakerIsNamed,\n type TranscriptTurn,\n} from \"../recordings\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\n\nconst defaultText = createOpenGeniText();\n\n/** The chart palette, one hue per voice. */\nconst SPEAKER_DOT: Record<number, string> = {\n 1: \"bg-chart-1\",\n 2: \"bg-chart-2\",\n 3: \"bg-chart-3\",\n 4: \"bg-chart-4\",\n 5: \"bg-chart-5\",\n 6: \"bg-chart-6\",\n};\n\n/**\n * A voice's hue, for its name and mentions; the shared rules below mix it.\n * Set inline, so the six slots cost no stylesheet rules.\n */\nexport function speakerHueStyle(slot: number | undefined): CSSProperties | undefined {\n return slot !== undefined && SPEAKER_DOT[slot]\n ? ({ \"--speaker-hue\": `var(--color-chart-${slot})` } as CSSProperties)\n : undefined;\n}\n\n/**\n * The hue mixed toward the text colour, so it reads on both themes: darker on\n * light, lighter on dark. Light takes more of the text colour (about 5:1 or\n * better on the page and on a mention's tint); dark keeps more hue at the\n * same contrast.\n */\nconst SPEAKER_TEXT =\n \"text-[color-mix(in_oklab,var(--speaker-hue)_50%,var(--color-fg))] dark:text-[color-mix(in_oklab,var(--speaker-hue)_62%,var(--color-fg))]\";\n\n/** A faint fill in the voice's hue, for a mention of that speaker. */\nconst SPEAKER_TINT = \"bg-[color-mix(in_oklab,var(--speaker-hue)_14%,transparent)]\";\n\n/** The text colour of a speaker's colour slot, with {@link speakerHueStyle}; muted when there is none. */\nexport function speakerTextClass(slot: number | undefined): string {\n return speakerHueStyle(slot) ? SPEAKER_TEXT : \"text-fg-muted\";\n}\n\n/** The faint fill of a speaker's colour slot, with {@link speakerHueStyle}; the chip surface when there is none. */\nexport function speakerTintClass(slot: number | undefined): string {\n return speakerHueStyle(slot) ? SPEAKER_TINT : \"bg-surface-2\";\n}\n\n/** A turn's pencil and ⋯: shown on hover or focus of the turn, always on touch. */\nconst TURN_ACTION =\n \"size-7 rounded-[8px] text-fg-subtle opacity-0 transition-opacity duration-[120ms] group-hover/turn:opacity-100 group-focus-within/turn:opacity-100 focus-visible:opacity-100 data-[state=open]:opacity-100 motion-reduce:transition-none pointer-coarse:size-11 pointer-coarse:opacity-100\";\n\nexport function SpeakerDot({ slot, className }: { slot: number | undefined; className?: string }) {\n return (\n <span\n aria-hidden=\"true\"\n className={cn(\n \"size-2 shrink-0 rounded-full\",\n SPEAKER_DOT[slot ?? 0] ?? \"bg-fg-subtle\",\n className,\n )}\n />\n );\n}\n\nexport type TranscriptActions = {\n nameSpeaker: (\n label: string,\n name: { personId: string } | { name: string } | null,\n ) => Promise<void>;\n /** Turn down a name suggested from a voice. */\n rejectSuggestion: (label: string) => Promise<void>;\n createPerson: (displayName: string) => Promise<RecordingPerson>;\n /**\n * Name a speaker as the person reading, linked to their account so their\n * own voice can be remembered. Null when there is no signed-in member.\n */\n nameSelf: ((label: string) => Promise<void>) | null;\n /** Who is reading, to tell their own entry in the people list apart. */\n viewerSubjectId: string | null;\n moveSegment: (segmentIndex: number, label: string) => Promise<void>;\n editSegment: (segmentIndex: number, text: string | null) => Promise<void>;\n /** Null when the workspace doesn't recognize people by voice. */\n voices: VoiceActions | null;\n};\n\n/** Remembering and forgetting voices, from a named speaker's menu. */\nexport type VoiceActions = {\n viewerSubjectId: string;\n /** Asks first when the person is someone from outside the workspace. */\n remember: (person: RecordingPerson) => void;\n forget: (person: RecordingPerson) => Promise<void>;\n};\n\n/** The speaker's name came from their voice and nobody has confirmed it yet. */\nexport function speakerIsSuggested(\n label: string | null,\n speakers: readonly RecordingSpeaker[],\n): RecordingSpeaker | null {\n if (!label) return null;\n const speaker = speakers.find((candidate) => candidate.label === label);\n return speaker?.source === \"suggested\" && speaker.personId ? speaker : null;\n}\n\n/** \"92% match\", from the voice similarity behind a suggestion. */\nexport function suggestionMatch(\n speaker: RecordingSpeaker,\n msg: OpenGeniText = defaultText,\n): string | null {\n return speaker.confidence === null\n ? null\n : msg(\"meetings.transcript.valueMatch\", {\n value: Math.round(Math.max(0, Math.min(1, speaker.confidence)) * 100),\n });\n}\n\nasync function withToast(failure: string, work: () => Promise<void>): Promise<boolean> {\n try {\n await work();\n return true;\n } catch (error) {\n toast.error(failure, {\n description: error instanceof Error ? userErrorText(error) : undefined,\n });\n return false;\n }\n}\n\n/**\n * \"Who is Speaker 2?\": pick a person, add a new name, or clear it. People\n * already named in this meeting come first as \"Same person as …\", because\n * picking one joins the two voices under one name.\n */\nexport function SpeakerNameMenu({\n label,\n displayName,\n speakers,\n people,\n actions,\n onAddNew,\n children,\n align = \"start\",\n defaultOpen,\n}: {\n label: string;\n displayName: string;\n speakers: readonly RecordingSpeaker[];\n people: readonly RecordingPerson[];\n actions: TranscriptActions;\n onAddNew: (label: string) => void;\n children: React.ReactNode;\n align?: \"start\" | \"end\";\n /** Open on first render, for previews. */\n defaultOpen?: boolean;\n}) {\n const msg = useOpenGeniText();\n const current = speakers.find((speaker) => speaker.label === label);\n const named = speakerIsNamed(label, speakers);\n const suggested = speakerIsSuggested(label, speakers);\n const inMeeting = useMemo(() => {\n const ids = new Set(\n speakers\n .filter((speaker) => speaker.label !== label && speaker.personId)\n .map((speaker) => speaker.personId!),\n );\n return people.filter((person) => ids.has(person.id) && person.id !== current?.personId);\n }, [people, speakers, label, current?.personId]);\n const viewerSubjectId = actions.viewerSubjectId;\n const others = useMemo(\n () =>\n people\n // A suggested person is already the first choice above, and the\n // reader is \"It's me\".\n .filter(\n (person) =>\n !inMeeting.includes(person) &&\n !(current?.source === \"suggested\" && person.id === current.personId) &&\n !(viewerSubjectId && person.memberSubjectId === viewerSubjectId),\n )\n .sort((a, b) => a.displayName.localeCompare(b.displayName))\n .slice(0, 12),\n [people, inMeeting, current?.source, current?.personId, viewerSubjectId],\n );\n const pick = (person: RecordingPerson) =>\n void withToast(msg(\"meetings.transcript.couldnTNameThisSpeaker\"), () =>\n actions.nameSpeaker(label, { personId: person.id }),\n );\n const nameSelf = actions.nameSelf;\n const isSelf = Boolean(\n viewerSubjectId &&\n current?.personId &&\n people.some(\n (person) => person.id === current.personId && person.memberSubjectId === viewerSubjectId,\n ),\n );\n const selfItem =\n nameSelf && !isSelf ? (\n <DropdownMenuItem\n onSelect={() =>\n void withToast(msg(\"meetings.transcript.couldnTNameThisSpeaker\"), () => nameSelf(label))\n }\n >\n <UserIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.itSMe\")}\n </DropdownMenuItem>\n ) : null;\n const currentPerson = current?.personId\n ? (people.find((candidate) => candidate.id === current.personId) ?? null)\n : null;\n const voiceItem =\n !suggested && currentPerson && actions.voices\n ? voiceMenuItem(currentPerson, actions.voices, msg)\n : null;\n return (\n <DropdownMenu {...(defaultOpen ? { defaultOpen } : {})}>\n <DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger>\n <DropdownMenuContent align={align} className=\"max-h-80 min-w-56\">\n {suggested ? (\n <>\n <DropdownMenuLabel className=\"grid gap-0.5\">\n <span>\n {msg(\"meetings.transcript.isThisDisplayname\", { displayName: displayName })}\n </span>\n <span className=\"text-xs leading-4 font-normal text-fg-muted\">\n {suggestionMatch(suggested, msg)\n ? msg(\"meetings.transcript.suggestedBecauseTheVoiceSounds\", {\n suggestionMatch: suggestionMatch(suggested, msg),\n })\n : msg(\"meetings.transcript.suggestedBecauseTheVoiceSounds2\")}\n </span>\n </DropdownMenuLabel>\n <DropdownMenuItem\n onSelect={() =>\n void withToast(msg(\"meetings.transcript.couldnTConfirmThisName\"), () =>\n actions.nameSpeaker(label, { personId: suggested.personId! }),\n )\n }\n >\n <CheckIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.yesItSDisplayname\", { displayName: displayName })}\n </DropdownMenuItem>\n <DropdownMenuItem\n onSelect={() =>\n void withToast(msg(\"meetings.transcript.couldnTTurnDownThis\"), () =>\n actions.rejectSuggestion(label),\n )\n }\n >\n <XIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.noLeaveUnnamed\")}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuLabel className=\"text-xs leading-4 font-normal text-fg-muted\">\n {msg(\"meetings.transcript.orPickWhoItIs\")}\n </DropdownMenuLabel>\n </>\n ) : (\n <DropdownMenuLabel>\n {msg(\"meetings.transcript.whoIsDisplayname\", { displayName: displayName })}\n </DropdownMenuLabel>\n )}\n {selfItem}\n {selfItem && inMeeting.length + others.length > 0 ? <DropdownMenuSeparator /> : null}\n {inMeeting.map((person) => (\n <DropdownMenuItem key={person.id} onSelect={() => pick(person)}>\n <span className=\"min-w-0 flex-1 truncate\">\n {msg(\"meetings.transcript.samePersonAsDisplayname\", {\n displayName: person.displayName,\n })}\n </span>\n </DropdownMenuItem>\n ))}\n {inMeeting.length > 0 && others.length > 0 ? <DropdownMenuSeparator /> : null}\n {others.map((person) => (\n <DropdownMenuItem key={person.id} onSelect={() => pick(person)}>\n <span className=\"min-w-0 flex-1 truncate\">{person.displayName}</span>\n {current?.personId === person.id && !suggested ? (\n <CheckIcon aria-hidden=\"true\" className=\"text-brand\" />\n ) : null}\n </DropdownMenuItem>\n ))}\n {inMeeting.length + others.length > 0 ? <DropdownMenuSeparator /> : null}\n <DropdownMenuItem onSelect={() => onAddNew(label)}>\n <UserPlusIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.someoneNew\")}\n </DropdownMenuItem>\n {named && !suggested ? (\n <DropdownMenuItem\n onSelect={() =>\n void withToast(msg(\"meetings.transcript.couldnTClearThisName\"), () =>\n actions.nameSpeaker(label, null),\n )\n }\n >\n <XIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.removeName\")}\n </DropdownMenuItem>\n ) : null}\n {voiceItem ? (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuLabel className=\"text-xs leading-4 font-normal text-fg-muted\">\n {msg(\"meetings.transcript.usedToSuggestNamesIn\")}\n </DropdownMenuLabel>\n {voiceItem}\n </>\n ) : null}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\n/**\n * \"Remember my voice\", \"Remember Maja's voice…\" or \"Forget …\": members only\n * decide for themselves, so another member's voice offers nothing here.\n */\nfunction voiceMenuItem(\n person: RecordingPerson,\n voices: VoiceActions,\n msg: OpenGeniText = defaultText,\n): React.ReactNode {\n const self = person.memberSubjectId === voices.viewerSubjectId;\n if (person.memberSubjectId && !self) return null;\n if (person.voice) {\n return (\n <DropdownMenuItem\n onSelect={() =>\n void withToast(msg(\"meetings.transcript.couldnTForgetThisVoice\"), () =>\n voices.forget(person),\n )\n }\n >\n <AudioLinesIcon aria-hidden=\"true\" />\n <span className=\"min-w-0 flex-1 truncate\">\n {self\n ? msg(\"meetings.transcript.forgetMyVoice\")\n : msg(\"meetings.transcript.forgetDisplaynameSVoice\", {\n displayName: person.displayName,\n })}\n </span>\n </DropdownMenuItem>\n );\n }\n return (\n <DropdownMenuItem onSelect={() => voices.remember(person)}>\n <AudioLinesIcon aria-hidden=\"true\" />\n <span className=\"min-w-0 flex-1 truncate\">\n {self\n ? msg(\"meetings.transcript.rememberMyVoice\")\n : msg(\"meetings.transcript.rememberDisplaynameSVoice\", {\n displayName: person.displayName,\n })}\n </span>\n </DropdownMenuItem>\n );\n}\n\n/** \"Name this speaker\": adds them to the people directory and names the voice. */\nexport function NewSpeakerNameDialog({\n label,\n displayName,\n actions,\n onClose,\n}: {\n label: string | null;\n displayName: string;\n actions: TranscriptActions;\n onClose: () => void;\n}) {\n const msg = useOpenGeniText();\n const [name, setName] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n return (\n <FormDialog\n open={label !== null}\n onOpenChange={(open) => {\n if (!open) {\n onClose();\n setName(\"\");\n setError(null);\n }\n }}\n title={msg(\"meetings.transcript.whoIsDisplayname\", { displayName: displayName })}\n description={msg(\"meetings.transcript.theNameIsAddedTo\")}\n submitLabel={msg(\"meetings.transcript.saveName\")}\n pendingLabel={msg(\"meetings.transcript.saving\")}\n submitDisabled={!name.trim()}\n error={error}\n onSubmit={async () => {\n if (!label || !name.trim()) return false;\n try {\n const person = await actions.createPerson(name.trim());\n await actions.nameSpeaker(label, { personId: person.id });\n } catch (cause) {\n setError(\n cause instanceof Error ? cause.message : msg(\"meetings.transcript.couldnTSaveThisName\"),\n );\n return false;\n }\n setName(\"\");\n setError(null);\n }}\n onSubmitted={onClose}\n >\n <FieldStack>\n <Field label={msg(\"meetings.transcript.name\")}>\n <TextInput\n value={name}\n maxLength={200}\n autoComplete=\"off\"\n onChange={(event) => setName(event.target.value)}\n placeholder={msg(\"meetings.transcript.forExampleMajaBerg\")}\n />\n </Field>\n </FieldStack>\n </FormDialog>\n );\n}\n\nfunction EditTurnDialog({\n turn,\n speakerName,\n onClose,\n actions,\n}: {\n turn: TranscriptTurn | null;\n speakerName: string;\n onClose: () => void;\n actions: TranscriptActions;\n}) {\n const msg = useOpenGeniText();\n const [drafts, setDrafts] = useState<Record<number, string>>({});\n const formId = useId();\n const changed =\n turn?.segments.some(\n (segment) => drafts[segment.index] !== undefined && drafts[segment.index] !== segment.text,\n ) ?? false;\n return (\n <FormDialog\n open={turn !== null}\n onOpenChange={(open) => {\n if (!open) {\n onClose();\n setDrafts({});\n }\n }}\n size=\"lg\"\n title={msg(\"meetings.transcript.correctTheWords\")}\n description={msg(\"meetings.transcript.fixWhatTheTranscriptGot\")}\n submitLabel={msg(\"meetings.transcript.save\")}\n pendingLabel={msg(\"meetings.transcript.saving\")}\n submitDisabled={!changed}\n onSubmit={async () => {\n if (!turn) return;\n const changes = turn.segments.filter(\n (segment) =>\n drafts[segment.index] !== undefined && drafts[segment.index] !== segment.text,\n );\n const ok = await withToast(\n msg(\"meetings.transcript.couldnTSaveTheCorrection\"),\n async () => {\n for (const segment of changes) {\n const text = drafts[segment.index]!.trim();\n await actions.editSegment(segment.index, text.length > 0 ? text : null);\n }\n },\n );\n if (!ok) return false;\n setDrafts({});\n }}\n onSubmitted={onClose}\n >\n <FieldStack>\n {turn?.segments.map((segment) => (\n <Field\n key={segment.index}\n label={msg(\"meetings.transcript.speakernameAtFormatclock\", {\n speakerName: speakerName,\n formatClock: formatClock(segment.startMilliseconds),\n })}\n >\n <TextArea\n id={`${formId}-${segment.index}`}\n rows={Math.min(8, Math.max(2, Math.ceil(segment.text.length / 80)))}\n value={drafts[segment.index] ?? segment.text}\n onChange={(event) =>\n setDrafts((current) => ({ ...current, [segment.index]: event.target.value }))\n }\n />\n </Field>\n ))}\n </FieldStack>\n </FormDialog>\n );\n}\n\nfunction MeetingTranscriptContent({\n segments,\n speakers,\n tracks,\n people,\n activeSegment,\n actions,\n onSeek,\n}: {\n segments: readonly RecordingTranscriptSegment[];\n speakers: readonly RecordingSpeaker[];\n tracks: readonly RecordingTrack[];\n people: readonly RecordingPerson[];\n /** The segment playing now. */\n activeSegment: number | null;\n actions: TranscriptActions;\n /** Null when there is no audio to play. */\n onSeek: ((milliseconds: number) => void) | null;\n}) {\n const msg = useOpenGeniText();\n const turns = useMemo(() => groupTranscriptTurns(segments), [segments]);\n const slots = useMemo(() => speakerColorSlots(segments), [segments]);\n const labels = useMemo(() => [...slots.keys()], [slots]);\n const [naming, setNaming] = useState<string | null>(null);\n const [editing, setEditing] = useState<TranscriptTurn | null>(null);\n const nameOf = (label: string | null) => speakerDisplayName(label, speakers, tracks, msg);\n const listRef = useRef<HTMLOListElement>(null);\n // Follow playback: keep the playing line in view while the reader is\n // following it, and stop following once they scroll elsewhere.\n const previousActive = useRef<number | null>(null);\n useEffect(() => {\n const list = listRef.current;\n if (!list || activeSegment === null) {\n previousActive.current = activeSegment;\n return;\n }\n const visible = (element: Element | null) => {\n if (!element) return false;\n const box = element.getBoundingClientRect();\n return box.bottom > 0 && box.top < window.innerHeight;\n };\n const previous =\n previousActive.current === null\n ? null\n : list.querySelector(`[data-segment=\"${previousActive.current}\"]`);\n const next = list.querySelector(`[data-segment=\"${activeSegment}\"]`);\n previousActive.current = activeSegment;\n if (!next || visible(next) || (previous && !visible(previous))) return;\n const reduce = window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches;\n next.scrollIntoView({ block: \"center\", behavior: reduce ? \"auto\" : \"smooth\" });\n }, [activeSegment]);\n\n return (\n <>\n <ol ref={listRef} className=\"grid gap-6\" aria-label={msg(\"meetings.transcript.transcript\")}>\n {turns.map((turn) => {\n const name = nameOf(turn.speakerLabel);\n const unnamed = turn.speakerLabel ? !speakerIsNamed(turn.speakerLabel, speakers) : false;\n const suggested = speakerIsSuggested(turn.speakerLabel, speakers);\n const slot = turn.speakerLabel ? slots.get(turn.speakerLabel) : undefined;\n const at = formatClock(turn.startMilliseconds);\n return (\n <li\n key={turn.key}\n data-turn={turn.key}\n className=\"group/turn grid max-w-[72ch] min-w-0 gap-1.5\"\n >\n <div className=\"flex min-w-0 items-center gap-2 pl-1\">\n {turn.speakerLabel ? (\n <SpeakerNameMenu\n label={turn.speakerLabel}\n displayName={name}\n speakers={speakers}\n people={people}\n actions={actions}\n onAddNew={setNaming}\n >\n <button\n type=\"button\"\n aria-label={\n unnamed\n ? msg(\"meetings.transcript.nameNameThisSpeaker\", { name: name })\n : suggested\n ? msg(\"meetings.transcript.nameSuggestedFromTheirVoice\", { name: name })\n : msg(\"meetings.transcript.nameChangeWhoThisIs\", { name: name })\n }\n className=\"group/speaker -mx-1.5 flex min-w-0 items-center gap-2 rounded-[6px] px-1.5 py-0.5 text-sm leading-5 font-semibold transition-colors duration-[120ms] hover:bg-hover data-[state=open]:bg-hover pointer-coarse:min-h-11\"\n >\n <span\n data-speaker-name=\"\"\n className={cn(\"truncate\", speakerTextClass(slot))}\n style={speakerHueStyle(slot)}\n >\n {name}\n </span>\n {suggested ? (\n <span className=\"shrink-0 rounded-full border border-dashed border-border-strong px-1.5 text-xs leading-4 font-normal text-fg-muted\">\n {msg(\"meetings.transcript.suggested\")}\n </span>\n ) : null}\n {unnamed ? (\n // An unnamed speaker always shows it can be named, not only on hover.\n <span className=\"flex shrink-0 items-center gap-1 text-xs leading-4 font-normal text-fg-muted group-hover/speaker:text-fg\">\n <PencilIcon aria-hidden=\"true\" className=\"size-3\" />\n {msg(\"meetings.transcript.name\")}\n </span>\n ) : (\n <ChevronDownIcon\n aria-hidden=\"true\"\n className=\"size-3.5 shrink-0 text-fg-subtle opacity-0 transition-opacity duration-[120ms] group-hover/speaker:opacity-100 group-focus-visible/speaker:opacity-100 group-data-[state=open]/speaker:opacity-100 pointer-coarse:opacity-100 motion-reduce:transition-none\"\n />\n )}\n </button>\n </SpeakerNameMenu>\n ) : (\n <span className=\"text-sm leading-5 font-semibold text-fg-muted\">{name}</span>\n )}\n {onSeek ? (\n <button\n type=\"button\"\n onClick={() => onSeek(turn.startMilliseconds)}\n className=\"rounded-[6px] px-1 text-xs leading-4 text-fg-muted tabular-nums underline-offset-2 transition-colors duration-[120ms] hover:text-fg hover:underline pointer-coarse:min-h-11\"\n aria-label={msg(\"meetings.transcript.playFromFormatclock\", {\n formatClock: at,\n })}\n >\n {at}\n </button>\n ) : (\n <span className=\"text-xs leading-4 text-fg-muted tabular-nums\">{at}</span>\n )}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={msg(\"meetings.transcript.correctTheWordsOfNameAt\", {\n name: name,\n formatClock: at,\n })}\n onClick={() => setEditing(turn)}\n className={cn(\"ml-auto\", TURN_ACTION)}\n >\n <PencilIcon />\n </Button>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={msg(\"meetings.transcript.moreActionsForNameAt\", {\n name: name,\n formatClock: at,\n })}\n className={TURN_ACTION}\n >\n <MoreHorizontalIcon />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"min-w-52\">\n {labels.length > 1 ? (\n <DropdownMenuSub>\n <DropdownMenuSubTrigger>\n <UsersIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.changeSpeaker\")}\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent className=\"min-w-48\">\n {labels\n .filter((label) => label !== turn.speakerLabel)\n .map((label) => (\n <DropdownMenuItem\n key={label}\n onSelect={() =>\n void withToast(\n msg(\"meetings.transcript.couldnTChangeTheSpeaker\"),\n async () => {\n for (const segment of turn.segments) {\n await actions.moveSegment(segment.index, label);\n }\n },\n )\n }\n >\n <SpeakerDot slot={slots.get(label)} />\n <span className=\"min-w-0 flex-1 truncate\">{nameOf(label)}</span>\n </DropdownMenuItem>\n ))}\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n ) : null}\n <DropdownMenuItem onSelect={() => setEditing(turn)}>\n <PencilIcon aria-hidden=\"true\" />\n {msg(\"meetings.transcript.correctTheWords\")}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n {/* A soft bubble, left-aligned for everyone, like a chat. */}\n <p\n data-turn-bubble=\"\"\n className=\"w-fit max-w-full rounded-[14px] rounded-tl-[4px] bg-surface-2 px-3.5 py-2 text-[15px] leading-6 text-pretty text-fg\"\n >\n {turn.segments.map((segment, position) => (\n <span key={segment.index}>\n {position > 0 ? \" \" : null}\n <span\n data-segment={segment.index}\n className={cn(\n \"rounded-[3px] transition-colors duration-[120ms] box-decoration-clone\",\n segment.index === activeSegment && \"bg-brand/15 text-fg\",\n onSeek && \"cursor-pointer hover:bg-hover\",\n )}\n onClick={onSeek ? () => onSeek(segment.startMilliseconds) : undefined}\n >\n {segment.text}\n </span>\n {segment.edited ? (\n <span className=\"sr-only\">{msg(\"meetings.transcript.corrected\")}</span>\n ) : null}\n </span>\n ))}\n </p>\n </li>\n );\n })}\n </ol>\n <NewSpeakerNameDialog\n label={naming}\n displayName={naming ? nameOf(naming) : \"\"}\n actions={actions}\n onClose={() => setNaming(null)}\n />\n <EditTurnDialog\n turn={editing}\n speakerName={editing ? nameOf(editing.speakerLabel) : \"\"}\n onClose={() => setEditing(null)}\n actions={actions}\n />\n </>\n );\n}\n\nexport function MeetingTranscript(props: ComponentProps<typeof MeetingTranscriptContent>) {\n return (\n <MeetingsOverlayScope>\n <MeetingTranscriptContent {...props} />\n </MeetingsOverlayScope>\n );\n}\n","import { createContext, useCallback, useContext, useRef, useState, type ReactNode } from \"react\";\n\nimport { useHostTheme } from \"../lib/host-theme\";\nimport { StandaloneOverlayRoot } from \"../ui/portal-container\";\n\nconst InsideScope = createContext(false);\n\n/**\n * The root of a meetings component, as the embedded chat's root is: it takes\n * light or dark and its surfaces from the page it sits on, so its page\n * background, sticky bars and cards match a host page instead of Opengeni's\n * own greys (inside Opengeni's app, or under an embed root that already did\n * this, nothing changes). Its menus and dialogs stay inside Opengeni's scoped\n * stylesheet and theme: they open in an `og-root` layer under <body> that\n * carries the component's tokens; inside an app that already provides a\n * portal container, that container is used. A component inside another one\n * (the transcript on a meeting's page) uses the outer scope.\n */\nexport function MeetingsOverlayScope({ children }: { children: ReactNode }) {\n const inside = useContext(InsideScope);\n if (inside) return <>{children}</>;\n return <MeetingsRoot>{children}</MeetingsRoot>;\n}\n\nfunction MeetingsRoot({ children }: { children: ReactNode }) {\n const root = useRef<HTMLDivElement | null>(null);\n const [source, setSource] = useState<HTMLDivElement | null>(null);\n const hostTheme = useHostTheme(root, {});\n const ref = useCallback((node: HTMLDivElement | null) => {\n root.current = node;\n setSource(node);\n }, []);\n return (\n // `og-root` re-derives the stylesheet's colors from the tokens set here.\n <div\n ref={ref}\n className=\"og-root\"\n style={{ ...hostTheme.style, display: \"contents\" }}\n data-og-theme={hostTheme.attribute}\n data-og-host-theme=\"\"\n >\n <InsideScope.Provider value>\n <StandaloneOverlayRoot source={source}>{children}</StandaloneOverlayRoot>\n </InsideScope.Provider>\n </div>\n );\n}\n","/**\n * Meetings: the recorder on top, then every meeting this person can see,\n * newest first. A row opens the meeting's own page. Rows still recording, in\n * progress elsewhere or transcribing say so and update on their own.\n */\nimport { useOpenGeniText } from \"../messages/runtime\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n type ComponentProps,\n} from \"react\";\nimport { AudioLinesIcon, LockIcon, SearchIcon, Trash2Icon } from \"lucide-react\";\nimport type { Recording } from \"@opengeni/contracts\";\nimport {\n formatDuration,\n meetingHereStatus,\n meetingPhase,\n meetingStatusLabel,\n meetingTitle,\n useRecordingModels,\n useRecordings,\n useRecordingsClient,\n type RecordingsClientOverride,\n} from \"../recordings\";\n\nimport { Button } from \"../ui/button\";\nimport { DropdownMenuItem } from \"../ui/dropdown-menu\";\nimport { EmptyState } from \"../ui/empty-state\";\nimport { ErrorMessage } from \"../ui/error-message\";\nimport { inAppClick } from \"../ui/in-app-click\";\nimport { Input } from \"../ui/input\";\nimport { ListRow, ListRowSkeleton, RowList, type RowListColumn } from \"../ui/list-row\";\nimport { LogoTile } from \"../ui/logo-tile\";\nimport { MetaChip } from \"../ui/meta-chip\";\nimport { Notice } from \"../ui/notice\";\nimport { PageHeader } from \"../ui/page-header\";\nimport { RelativeTime } from \"../ui/relative-time\";\nimport { StatusBadge } from \"../ui/status-badge\";\n\nimport { DeleteMeetingDialog } from \"./delete-meeting-dialog\";\nimport { RecorderPanel, useOnline } from \"./recorder-panel\";\nimport { useMeetingRecorder, usePendingMeetingStart } from \"./recorder-context\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\n\nfunction useDebounced<T>(value: T, delay: number): T {\n const [debounced, setDebounced] = useState(value);\n useEffect(() => {\n const timer = window.setTimeout(() => setDebounced(value), delay);\n return () => window.clearTimeout(timer);\n }, [value, delay]);\n return debounced;\n}\n\nfunction useNarrow(): boolean {\n const query = \"(max-width: 639px)\";\n const [narrow, setNarrow] = useState(\n () => typeof window !== \"undefined\" && window.matchMedia?.(query).matches === true,\n );\n useEffect(() => {\n const media = window.matchMedia?.(query);\n if (!media) return;\n const update = () => setNarrow(media.matches);\n update();\n media.addEventListener(\"change\", update);\n return () => media.removeEventListener(\"change\", update);\n }, []);\n return narrow;\n}\n\nfunction MeetingsListPageContent({\n workspaceId,\n liveTranscriptDefault,\n liveTranscript = true,\n defaultLanguage,\n recordings: recordingsClient,\n meetingHref,\n onOpen,\n externalRef = null,\n notice = null,\n header = true,\n recordingOff = null,\n viewerName = null,\n}: {\n workspaceId: string;\n /**\n * Whether the recorder starts with the live transcript on. By default the\n * workspace's setting, from the server.\n */\n liveTranscriptDefault?: boolean;\n /** Offer the live transcript preview at all; false hides it even when a live model is connected. */\n liveTranscript?: boolean;\n /**\n * The language the recorder starts on; null detects it. By default the\n * workspace's meeting language, from the server.\n */\n defaultLanguage?: string | null;\n /** A recordings client to use instead of the app's, for previews. */\n recordings?: RecordingsClientOverride[\"recordings\"];\n meetingHref: (recordingId: string) => string;\n onOpen: (recordingId: string) => void;\n /**\n * Show only the meetings with this id of the host's, such as a project, and\n * give new recordings started here the same id.\n */\n externalRef?: string | null;\n /** A short line shown before every start, such as a reminder to tell the people present. */\n notice?: ReactNode;\n /** Show the page title; false when the list sits inside a page of the host's. */\n header?: boolean;\n /**\n * Shown instead of the recorder when the host doesn't let this person record\n * here, such as a setting an administrator has to turn on first. Meetings\n * already recorded stay listed, and a recording already underway keeps its controls.\n */\n recordingOff?: ReactNode;\n /** The person recording's name, for their microphone's live text beside computer or tab audio. */\n viewerName?: string | null;\n}) {\n const msg = useOpenGeniText();\n const columns: RowListColumn[] = [\n { id: \"length\", label: msg(\"meetings.listPage.length\"), width: 96 },\n { id: \"recorded\", label: msg(\"meetings.listPage.recorded\"), width: 148 },\n ];\n const [search, setSearch] = useState(\"\");\n const query = useDebounced(search.trim(), 250);\n const override = { workspaceId, ...(recordingsClient ? { recordings: recordingsClient } : {}) };\n const list = useRecordings({\n ...override,\n ...(query ? { query } : {}),\n ...(externalRef ? { externalRef } : {}),\n });\n const { client } = useRecordingsClient(override);\n const {\n recorder,\n finished,\n workspaceId: recorderWorkspaceId,\n openMeeting,\n } = useMeetingRecorder();\n const online = useOnline();\n // A recording started in another workspace keeps going here; its meeting\n // opens in its own workspace.\n const openRecorded = useCallback(\n (recordingId: string) => {\n if (\n recorderWorkspaceId &&\n recorderWorkspaceId !== workspaceId &&\n openMeeting(recordingId, recorderWorkspaceId)\n ) {\n return;\n }\n onOpen(recordingId);\n },\n [recorderWorkspaceId, workspaceId, openMeeting, onOpen],\n );\n const models = useRecordingModels(override);\n const liveModel = models.liveModels.find((entry) => entry.available) ?? null;\n // A desktop call notification's Record waits for the live model list, so\n // the recording gets the same live-preview default as a click on Start.\n const pendingStart = usePendingMeetingStart();\n const autoStart = useMemo(\n () => ({ pending: pendingStart.request !== null && !models.loading, take: pendingStart.take }),\n [pendingStart.request, pendingStart.take, models.loading],\n );\n const narrow = useNarrow();\n const [pendingDelete, setPendingDelete] = useState<Recording | null>(null);\n\n // A recording that finished uploading in this tab changes state on the server.\n const refresh = list.refresh;\n const finishedCount = finished.length;\n useEffect(() => {\n if (finishedCount > 0) void refresh();\n }, [finishedCount, refresh]);\n // A recording that just started shows up in the list as soon as the server has it.\n const liveId = recorder?.upload?.created ? recorder.recordingId : null;\n const lastLiveId = useRef<string | null>(null);\n useEffect(() => {\n if (liveId && liveId !== lastLiveId.current) {\n lastLiveId.current = liveId;\n void refresh();\n }\n }, [liveId, refresh]);\n\n const loading = list.loading && list.recordings.length === 0;\n const empty = !list.loading && !list.error && list.recordings.length === 0;\n const showRecorder = recordingOff === null || (recorder !== null && recorder.state !== \"idle\");\n\n return (\n <>\n {header ? (\n <PageHeader\n icon={<AudioLinesIcon />}\n title={msg(\"meetings.listPage.meetings\")}\n description={msg(\"meetings.listPage.recordAMeetingAndGet\")}\n />\n ) : null}\n <div className={header ? \"mt-2 grid gap-8\" : \"grid gap-8\"}>\n {showRecorder ? (\n <RecorderPanel\n recorder={recorder}\n onStopped={openRecorded}\n onOpenNotes={openRecorded}\n defaultLanguage={defaultLanguage !== undefined ? defaultLanguage : models.language}\n autoStart={autoStart}\n externalRef={externalRef}\n notice={notice}\n viewerName={viewerName}\n liveTranscript={\n liveTranscript && liveModel\n ? {\n defaultOn: liveTranscriptDefault ?? models.liveTranscript ?? false,\n usdPerHour: liveModel.usdPerHour,\n }\n : null\n }\n />\n ) : (\n <Notice tone=\"info\">{recordingOff}</Notice>\n )}\n {recorder && recorder.recovered.length > 0 ? (\n <Notice tone=\"info\">\n {msg(\"meetings.listPage.earlierRecordingsWereStillSaved\", {\n count: recorder.recovered.length,\n })}\n </Notice>\n ) : null}\n <div className=\"grid gap-3\">\n {list.recordings.length > 0 || query ? (\n <div className=\"relative max-w-80\">\n <SearchIcon\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-fg-subtle\"\n />\n <Input\n type=\"search\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n placeholder={msg(\"meetings.listPage.searchMeetings\")}\n aria-label={msg(\"meetings.listPage.searchMeetings\")}\n className=\"h-9 pl-9 pointer-coarse:h-11\"\n />\n </div>\n ) : null}\n {loading ? (\n <RowList\n label={msg(\"meetings.listPage.meetings\")}\n columns={narrow ? [] : columns}\n flush\n busy\n >\n <ListRowSkeleton count={4} />\n </RowList>\n ) : list.error && list.recordings.length === 0 ? (\n <ErrorMessage\n align=\"center\"\n title={msg(\"meetings.listPage.couldnTLoadMeetings\")}\n details={[{ label: msg(\"meetings.listPage.error\"), value: list.error.message }]}\n action={\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void list.refresh()}\n className=\"pointer-coarse:h-11\"\n >\n {msg(\"meetings.listPage.tryAgain\")}\n </Button>\n }\n >\n {msg(\"meetings.listPage.checkYourConnectionThenTry\")}\n </ErrorMessage>\n ) : empty ? (\n query ? (\n <EmptyState\n variant=\"inline\"\n title={msg(\"meetings.listPage.noMeetingsMatchQuery\", { query: query })}\n description={msg(\"meetings.listPage.searchFindsWordsInMeeting\")}\n />\n ) : (\n <EmptyState\n variant=\"page\"\n icon={<AudioLinesIcon />}\n title={msg(\"meetings.listPage.noMeetingsYet\")}\n description={\n showRecorder ? msg(\"meetings.listPage.startARecordingAboveWhen\") : undefined\n }\n className=\"pt-8\"\n />\n )\n ) : (\n <RowList\n label={msg(\"meetings.listPage.meetings\")}\n columns={narrow ? [] : columns}\n flush\n >\n {list.recordings.map((recording) => {\n // Stopped here, its last audio is on its way: Transcribing, not In progress.\n const here =\n recording.state === \"capturing\"\n ? meetingHereStatus(recorder, recording.id, online)\n : null;\n const status = meetingStatusLabel(\n here === \"transcribing\"\n ? { kind: \"transcribing\", version: null }\n : meetingPhase(recording),\n msg,\n );\n // Recording here until Stop: after it, the row reads Transcribing.\n const isLive = here === \"recording\" || here === \"paused\";\n return (\n <ListRow\n key={recording.id}\n leading={<LogoTile icon={<AudioLinesIcon />} />}\n title={meetingTitle(recording, msg)}\n titleAddon={\n recording.sourceWorkspace ? (\n // The person's own Only me meeting, stored in another\n // workspace of the organization: say which.\n <MetaChip icon={<LockIcon />}>\n <span className=\"sr-only\">\n {msg(\"meetings.listPage.onlyMeRecordedIn\", {\n workspace: recording.sourceWorkspace.name,\n })}\n </span>\n <span aria-hidden=\"true\">{recording.sourceWorkspace.name}</span>\n </MetaChip>\n ) : recording.visibility === \"private\" ? (\n <MetaChip icon={<LockIcon />}>\n <span className={narrow ? \"sr-only\" : undefined}>\n {msg(\"meetings.listPage.onlyMe\")}\n </span>\n </MetaChip>\n ) : undefined\n }\n status={\n isLive ? (\n here === \"paused\" ? (\n <StatusBadge variant=\"dot\" tone=\"neutral\">\n {msg(\"meetings.recorderPanel.paused\")}\n </StatusBadge>\n ) : (\n <StatusBadge variant=\"dot\" tone=\"danger\" pulse>\n {msg(\"meetings.listPage.recording\")}\n </StatusBadge>\n )\n ) : status ? (\n <StatusBadge\n variant=\"dot\"\n tone={status.tone}\n pulse={status.tone === \"progress\"}\n >\n {status.label}\n </StatusBadge>\n ) : undefined\n }\n meta={\n narrow\n ? [\n <RelativeTime key=\"recorded\" date={recording.startedAt} />,\n recording.durationMilliseconds > 0\n ? formatDuration(recording.durationMilliseconds, msg)\n : null,\n ].filter(Boolean)\n : undefined\n }\n cells={{\n length:\n recording.durationMilliseconds > 0 ? (\n <span className=\"tabular-nums\">\n {formatDuration(recording.durationMilliseconds, msg)}\n </span>\n ) : (\n <span className=\"text-fg-subtle\">—</span>\n ),\n recorded: <RelativeTime date={recording.startedAt} />,\n }}\n menu={\n <DropdownMenuItem\n variant=\"destructive\"\n onSelect={() => setPendingDelete(recording)}\n >\n <Trash2Icon aria-hidden=\"true\" />\n {msg(\"meetings.listPage.deleteMeeting\")}\n </DropdownMenuItem>\n }\n menuLabel={msg(\"meetings.listPage.moreActionsForTitle\", {\n title: meetingTitle(recording, msg),\n })}\n href={meetingHref(recording.id)}\n linkProps={{ onClick: inAppClick(() => onOpen(recording.id)) }}\n />\n );\n })}\n </RowList>\n )}\n {list.hasMore ? (\n <div className=\"flex justify-center\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={list.loadingMore}\n onClick={() => void list.loadMore()}\n className=\"pointer-coarse:h-11\"\n >\n {list.loadingMore\n ? msg(\"meetings.listPage.loading\")\n : msg(\"meetings.listPage.showOlderMeetings\")}\n </Button>\n </div>\n ) : null}\n </div>\n </div>\n <DeleteMeetingDialog\n recording={\n pendingDelete && { id: pendingDelete.id, title: meetingTitle(pendingDelete, msg) }\n }\n onClose={() => setPendingDelete(null)}\n onDelete={async (recordingId) => {\n await client.deleteRecording(workspaceId, recordingId);\n }}\n onDeleted={() => void list.refresh()}\n />\n </>\n );\n}\n\nexport function MeetingsListPage(props: ComponentProps<typeof MeetingsListPageContent>) {\n return (\n <MeetingsOverlayScope>\n <MeetingsListPageContent {...props} />\n </MeetingsOverlayScope>\n );\n}\n","import type { ComponentProps } from \"react\";\nimport { useOpenGeniText } from \"../messages/runtime\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\nimport type { Recording } from \"@opengeni/contracts\";\n\nimport { ConfirmDialog } from \"../ui/confirm-dialog\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\n\nfunction DeleteMeetingDialogContent({\n recording,\n onClose,\n onDelete,\n onDeleted,\n}: {\n recording: Pick<Recording, \"id\" | \"title\"> | null;\n onClose: () => void;\n onDelete: (recordingId: string) => Promise<void>;\n onDeleted: () => void;\n}) {\n const msg = useOpenGeniText();\n return (\n <ConfirmDialog\n open={recording !== null}\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n title={\n recording\n ? msg(\"meetings.deleteDialog.deleteTitle\", { title: recording.title })\n : msg(\"meetings.deleteDialog.deleteMeeting\")\n }\n description={msg(\"meetings.deleteDialog.thisDeletesTheAudioEvery\")}\n confirmLabel={msg(\"meetings.deleteDialog.deleteMeeting2\")}\n pendingLabel={msg(\"meetings.deleteDialog.deleting\")}\n onConfirm={async () => {\n if (!recording) return;\n try {\n await onDelete(recording.id);\n } catch (error) {\n toast.error(msg(\"meetings.deleteDialog.couldnTDeleteThisMeeting\"), {\n description: error instanceof Error ? userErrorText(error) : undefined,\n });\n return false;\n }\n toast.success(msg(\"meetings.deleteDialog.meetingDeleted\"));\n onDeleted();\n }}\n />\n );\n}\n\n/** \"Delete 'Weekly sync'?\": removes the audio, every transcript and the speaker names. */\nexport function DeleteMeetingDialog(props: ComponentProps<typeof DeleteMeetingDialogContent>) {\n return (\n <MeetingsOverlayScope>\n <DeleteMeetingDialogContent {...props} />\n </MeetingsOverlayScope>\n );\n}\n","/**\n * One meeting's own page: back to Meetings, the title with who can see it,\n * Summary · Transcript · Notepad under it, then the player and the open tab.\n * Summary is the written notes (with mention chips and Copy), Transcript the\n * turns as speaker bubbles, Notepad what people jotted down; Summary and\n * Transcript end with \"Ask about this meeting\" when the host answers it. The\n * quiet card on the right names the speakers and says which transcript\n * version this is, with Transcribe again.\n *\n * Until the transcript exists the page says where the meeting is: still\n * recording here (with Pause and Stop, so taking notes never hides it), not\n * finished yet on another device, transcribing, or failed with the reason and\n * what to try. Audio uploads while it records, so after Stop it reads\n * Transcribing, not Uploading.\n */\nimport { useOpenGeniText, createOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\nimport { regionRestrictedText } from \"../inference-region\";\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport {\n AudioLinesIcon,\n CheckIcon,\n ChevronDownIcon,\n CreditCardIcon,\n GlobeIcon,\n LayersIcon,\n LoaderCircleIcon,\n LockIcon,\n PencilIcon,\n RefreshCwIcon,\n Trash2Icon,\n} from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\nimport type {\n Recording,\n RecordingNote,\n RecordingPerson,\n RecordingTranscriptVersion,\n RecordingTranscriptionModel,\n RecordingVisibility,\n} from \"@opengeni/contracts\";\nimport {\n activeSegmentIndex,\n defaultSpeakerName,\n formatDuration,\n languageName,\n meetingHereStatus,\n meetingPhase,\n meetingUploadFailure,\n ownerLiveLaneName,\n speakerColorSlots,\n speakerDisplayName,\n speakerIsNamed,\n meetingTitle,\n transcribingText,\n transcriptErrorText,\n transcriptFixModel,\n transcriptNeedsCredits,\n useRecording,\n useRecordingModels,\n useRecordingNotes,\n useRecordingPeople,\n useRecordingsClient,\n useLiveTranscript,\n useTranscript,\n type MeetingHereStatus,\n type RecordingsClientOverride,\n} from \"../recordings\";\n\nimport { Button } from \"../ui/button\";\nimport { ConfirmDialog } from \"../ui/confirm-dialog\";\nimport {\n DetailAside,\n DetailAsideItem,\n DetailMeta,\n DetailPage,\n DetailPageBody,\n DetailPageHeader,\n} from \"../ui/detail-page\";\nimport { DetailSection } from \"../ui/detail-sheet\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"../ui/dropdown-menu\";\nimport { EmptyState } from \"../ui/empty-state\";\nimport { ErrorMessage } from \"../ui/error-message\";\nimport { Field, FieldStack, TextInput } from \"../ui/field\";\nimport { FormDialog } from \"../ui/form-dialog\";\nimport { MoreMenu } from \"../ui/page-actions\";\nimport { Notice } from \"../ui/notice\";\nimport { formatAbsoluteTime } from \"../ui/relative-time\";\nimport { SegmentedControl } from \"../ui/segmented-control\";\nimport { NativeSelect, type SelectOption } from \"../ui/select-menu\";\nimport { Skeleton } from \"../ui/skeleton\";\nimport { cn } from \"../app/lib/utils\";\nimport {\n WorkspaceReachFields,\n type ReachWorkspace,\n type WorkspaceReach,\n} from \"../app/components/workspace-reach\";\n\nimport { DeleteMeetingDialog } from \"./delete-meeting-dialog\";\nimport { DETECT_LANGUAGE, meetingLanguageOptions } from \"./meeting-languages\";\nimport {\n MeetingPlayer,\n type MeetingPlayerHandle,\n type MeetingPlayerSource,\n} from \"./meeting-player\";\nimport {\n MeetingTranscript,\n NewSpeakerNameDialog,\n SpeakerDot,\n SpeakerNameMenu,\n speakerIsSuggested,\n type TranscriptActions,\n} from \"./meeting-transcript\";\nimport { liveSpeakerName, RecordingBar, recorderLiveLines, useOnline } from \"./recorder-panel\";\nimport { LiveTranscript, liveStatus } from \"./live-transcript\";\nimport { MeetingAsk, type MeetingAskRequest, type MeetingAskResult } from \"./meeting-ask\";\nimport { meetingMentionResolver } from \"./meeting-mentions\";\nimport { useAnnounceMeetingOnScreen } from \"./meeting-on-screen\";\nimport { useUiEventTarget } from \"../app/lib/ui-events\";\nimport { MeetingNotepad, MeetingNotesSection, MeetingSummary } from \"./meeting-notes\";\nimport { useMeetingRecorder, type MeetingRecorder } from \"./recorder-context\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\nimport { StickyBarEdge, useStuckToTop } from \"./sticky-bar-edge\";\n\nconst defaultText = createOpenGeniText();\n\nfunction errorText(error: unknown): string | undefined {\n return error instanceof Error ? userErrorText(error) : undefined;\n}\n\nfunction isNotFound(error: Error | null): boolean {\n return Boolean(error && /not found|404/iu.test(error.message));\n}\n\n/**\n * Fresh playback links for every prepared track. Links expire, so a failed one refetches.\n * While the meeting is processed, the player waits until every recorded track can\n * play: the first track alone sounds as if the rest (the call's side) was never recorded.\n */\nfunction useTrackSources(\n recording: Recording | null,\n getAudio: (trackNumber: number) => Promise<{ url: string }>,\n): { sources: MeetingPlayerSource[]; reload: () => void } {\n const [sources, setSources] = useState<MeetingPlayerSource[]>([]);\n const [generation, setGeneration] = useState(0);\n const state = recording?.state;\n const playable = useMemo(() => {\n const tracks = recording?.tracks ?? [];\n const partial =\n state === \"processing\" && tracks.some((track) => track.chunkCount > 0 && !track.playable);\n return partial\n ? []\n : tracks.filter((track) => track.playable).map((track) => track.trackNumber);\n }, [recording?.tracks, state]);\n const key = playable.join(\",\");\n const getAudioRef = useRef(getAudio);\n getAudioRef.current = getAudio;\n useEffect(() => {\n if (!key) {\n setSources([]);\n return;\n }\n let cancelled = false;\n void Promise.all(\n key.split(\",\").map(async (value) => {\n const trackNumber = Number(value);\n try {\n const audio = await getAudioRef.current(trackNumber);\n return { trackNumber, url: audio.url };\n } catch {\n return null;\n }\n }),\n ).then((loaded) => {\n if (!cancelled) {\n setSources(loaded.filter((source): source is MeetingPlayerSource => source !== null));\n }\n });\n return () => {\n cancelled = true;\n };\n }, [key, generation]);\n const reload = useCallback(() => setGeneration((value) => value + 1), []);\n return { sources, reload };\n}\n\nfunction RenameDialog({\n open,\n title,\n onClose,\n onRename,\n}: {\n open: boolean;\n title: string;\n onClose: () => void;\n onRename: (title: string) => Promise<void>;\n}) {\n const msg = useOpenGeniText();\n const [value, setValue] = useState(title);\n const [error, setError] = useState<string | null>(null);\n useEffect(() => {\n if (open) {\n setValue(title);\n setError(null);\n }\n }, [open, title]);\n return (\n <FormDialog\n open={open}\n onOpenChange={(next) => {\n if (!next) onClose();\n }}\n title={msg(\"meetings.detailPage.renameMeeting\")}\n submitLabel={msg(\"meetings.detailPage.save\")}\n pendingLabel={msg(\"meetings.detailPage.saving\")}\n submitDisabled={!value.trim() || value.trim() === title}\n error={error}\n onSubmit={async () => {\n try {\n await onRename(value.trim());\n } catch (cause) {\n setError(errorText(cause) ?? msg(\"meetings.detailPage.couldnTRenameThisMeeting\"));\n return false;\n }\n }}\n onSubmitted={onClose}\n >\n <FieldStack>\n <Field label={msg(\"meetings.detailPage.title\")}>\n <TextInput\n value={value}\n maxLength={300}\n onChange={(event) => setValue(event.target.value)}\n />\n </Field>\n </FieldStack>\n </FormDialog>\n );\n}\n\n/**\n * Where the owner's own Only me meeting works: the workspace that stores it\n * and their Personal workspace always, plus the ones they pick, or all of\n * their workspaces in the organization. Only they, and agent turns they\n * start, see it in any of them.\n */\nfunction MeetingReachDialog({\n open,\n recording,\n hereId,\n workspaces,\n organizationName,\n onClose,\n onSave,\n}: {\n open: boolean;\n recording: Recording;\n /** The workspace the page was opened from. */\n hereId: string;\n workspaces: readonly ReachWorkspace[];\n organizationName: string;\n onClose: () => void;\n /** Saves the other workspaces it works in (null for all), and says whether it still works here. */\n onSave: (reachWorkspaceIds: string[] | null, leavesHere: boolean) => Promise<void>;\n}) {\n const msg = useOpenGeniText();\n const saved = recording.reachWorkspaceIds ?? null;\n const savedKey = saved === null ? null : saved.join(\",\");\n const [value, setValue] = useState<WorkspaceReach>({\n workspaceIds: saved,\n personalWorkspaces: true,\n });\n const [error, setError] = useState<string | null>(null);\n useEffect(() => {\n if (open) {\n setValue({\n workspaceIds: savedKey === null ? null : savedKey.split(\",\").filter(Boolean),\n personalWorkspaces: true,\n });\n setError(null);\n }\n }, [open, savedKey]);\n const home = recording.workspaceId;\n const here = workspaces.find((workspace) => workspace.id === hereId);\n const chosen =\n value.workspaceIds === null ? null : value.workspaceIds.filter((id) => id !== home).sort();\n // Opened from another workspace it was turned on in, which it would leave.\n const leavesHere =\n hereId !== home && here?.personal !== true && chosen !== null && !chosen.includes(hereId);\n const unchanged =\n chosen === null\n ? saved === null\n : saved !== null && [...saved].sort().join(\",\") === chosen.join(\",\");\n return (\n <FormDialog\n open={open}\n onOpenChange={(next) => {\n if (!next) onClose();\n }}\n title={msg(\"meetings.detailPage.availableIn\")}\n description={msg(\"meetings.detailPage.onlyYouSeeItInThese\")}\n submitLabel={msg(\"meetings.detailPage.save\")}\n pendingLabel={msg(\"meetings.detailPage.saving\")}\n submitDisabled={unchanged}\n error={error}\n onSubmit={async () => {\n try {\n await onSave(chosen, leavesHere);\n } catch (cause) {\n setError(errorText(cause) ?? msg(\"meetings.detailPage.couldnTChangeWhereItWorks\"));\n return false;\n }\n }}\n onSubmitted={onClose}\n >\n <div className=\"flex min-w-0 flex-col gap-4\">\n <WorkspaceReachFields\n owner={{ kind: \"person\" }}\n organizationName={organizationName}\n label={msg(\"meetings.detailPage.availableIn\")}\n labelHidden\n value={value}\n onChange={setValue}\n workspaces={workspaces}\n hereId={hereId}\n alwaysIncluded={{ [home]: msg(\"meetings.detailPage.recordedThereAlwaysIncluded\") }}\n // Switching from All keeps the workspace it was opened from.\n seedSelected={() => (hereId !== home && here?.personal !== true ? [hereId] : [])}\n personalWorkspaces=\"always\"\n />\n {leavesHere ? (\n <Notice tone=\"info\" live=\"polite\">\n {msg(\"meetings.detailPage.itWillNoLongerShowHere\")}\n </Notice>\n ) : null}\n </div>\n </FormDialog>\n );\n}\n\n/**\n * The models \"Transcribe again\" offers. One that can't be used says why:\n * \"Not supported in EU\" when EU-only switched it off, otherwise what to connect.\n */\nexport function transcribeAgainModelOptions(\n models: readonly Pick<\n RecordingTranscriptionModel,\n | \"providerId\"\n | \"providerName\"\n | \"model\"\n | \"name\"\n | \"available\"\n | \"unavailableReason\"\n | \"usdPerHour\"\n >[],\n msg: OpenGeniText = defaultText,\n): SelectOption[] {\n return models.map((entry) => ({\n value: `${entry.providerId}/${entry.model}`,\n label: entry.name,\n meta:\n entry.usdPerHour !== null\n ? msg(\"meetings.detailPage.valuePerHour\", { value: entry.usdPerHour.toFixed(2) })\n : entry.providerName,\n disabled: !entry.available,\n disabledReason: entry.available\n ? undefined\n : (regionRestrictedText(msg, entry.unavailableReason) ??\n msg(\"meetings.detailPage.connectProvidernameFirst\", { providerName: entry.providerName })),\n }));\n}\n\n/**\n * What transcribing a meeting again costs at a model's hourly price. Each\n * recorded track (a microphone beside computer audio, say) is transcribed and\n * billed on its own, so a two-track hour costs two hours.\n */\nexport function transcribeAgainEstimate(\n recording: Pick<Recording, \"durationMilliseconds\" | \"tracks\">,\n usdPerHour: number | null | undefined,\n): { usd: number; tracks: number } | null {\n if (usdPerHour == null) return null;\n const recorded = recording.tracks.filter(\n (track) => track.chunkCount > 0 && track.durationMilliseconds > 0,\n );\n const milliseconds =\n recorded.length > 0\n ? recorded.reduce((total, track) => total + track.durationMilliseconds, 0)\n : recording.durationMilliseconds;\n if (milliseconds <= 0) return null;\n return { usd: (usdPerHour * milliseconds) / 3_600_000, tracks: Math.max(1, recorded.length) };\n}\n\nfunction TranscribeAgainDialog({\n open,\n recording,\n models,\n defaultModel,\n onClose,\n onRun,\n}: {\n open: boolean;\n recording: Recording;\n models: ReturnType<typeof useRecordingModels>[\"models\"];\n defaultModel: ReturnType<typeof useRecordingModels>[\"defaultModel\"];\n onClose: () => void;\n onRun: (options: {\n providerId: string;\n model: string;\n /** Null detects it, even when the workspace names a meeting language. */\n language: string | null;\n /** How many people speak; speaker detection finds that many. */\n speakers?: number;\n }) => Promise<void>;\n}) {\n const msg = useOpenGeniText();\n const current = recording.transcript;\n const initialModel = current\n ? `${current.providerId}/${current.model}`\n : defaultModel\n ? `${defaultModel.providerId}/${defaultModel.model}`\n : \"\";\n const [model, setModel] = useState(initialModel);\n const [language, setLanguage] = useState<string>(\n recording.transcription.language ?? DETECT_LANGUAGE,\n );\n const initialSpeakers = recording.transcription.speakers ?? recording.transcription.maxSpeakers;\n const [speakers, setSpeakers] = useState(initialSpeakers ? String(initialSpeakers) : \"\");\n const [error, setError] = useState<string | null>(null);\n useEffect(() => {\n if (open) {\n setModel(initialModel);\n setError(null);\n }\n }, [open, initialModel]);\n const modelOptions = transcribeAgainModelOptions(models, msg);\n const selected = models.find((entry) => `${entry.providerId}/${entry.model}` === model);\n const estimate = transcribeAgainEstimate(recording, selected?.usdPerHour);\n const duration = formatDuration(recording.durationMilliseconds, msg);\n const languageOptions = meetingLanguageOptions(language, undefined, msg);\n const speakerCount = speakers.trim() ? Number(speakers) : undefined;\n const speakersInvalid =\n speakerCount !== undefined &&\n (!Number.isInteger(speakerCount) || speakerCount < 1 || speakerCount > 32);\n // Speakers come from the model, or from Opengeni's own speaker detection\n // when this deployment has it (it made the current transcript's).\n const tellsSpeakersApart =\n selected?.capabilities.diarization === true || current?.diarization === \"ours\";\n return (\n <FormDialog\n open={open}\n onOpenChange={(next) => {\n if (!next) onClose();\n }}\n title={msg(\"meetings.detailPage.transcribeAgain\")}\n description={msg(\"meetings.detailPage.makesANewTranscriptNotesToo\")}\n submitLabel={msg(\"meetings.detailPage.transcribe\")}\n pendingLabel={msg(\"meetings.detailPage.starting\")}\n submitDisabled={!selected || !selected.available || speakersInvalid}\n error={error}\n onSubmit={async () => {\n if (!selected) return false;\n try {\n await onRun({\n providerId: selected.providerId,\n model: selected.model,\n language: language === DETECT_LANGUAGE ? null : language,\n ...(speakerCount !== undefined && tellsSpeakersApart ? { speakers: speakerCount } : {}),\n });\n } catch (cause) {\n setError(errorText(cause) ?? msg(\"meetings.detailPage.couldnTStartTranscribing\"));\n return false;\n }\n }}\n onSubmitted={onClose}\n >\n <FieldStack>\n <Field\n label={msg(\"meetings.detailPage.model\")}\n hint={\n estimate !== null\n ? estimate.usd < 0.01\n ? msg(\"meetings.detailPage.aboutLessThan001\", { duration })\n : estimate.tracks > 1\n ? msg(\"meetings.detailPage.aboutEstimateForTracks\", {\n estimate: estimate.usd.toFixed(2),\n duration,\n count: estimate.tracks,\n })\n : msg(\"meetings.detailPage.aboutEstimateForThisDuration\", {\n estimate: estimate.usd.toFixed(2),\n duration,\n })\n : undefined\n }\n >\n <NativeSelect options={modelOptions} value={model} onValueChange={setModel} />\n </Field>\n <Field\n label={msg(\"meetings.detailPage.language\")}\n hint={msg(\"meetings.detailPage.setItWhenTheMeeting\")}\n >\n <NativeSelect options={languageOptions} value={language} onValueChange={setLanguage} />\n </Field>\n {tellsSpeakersApart ? (\n <Field\n label={msg(\"meetings.detailPage.numberOfSpeakers\")}\n optional\n hint={msg(\"meetings.detailPage.leaveEmptyToLetThe\")}\n error={speakersInvalid ? msg(\"meetings.detailPage.enterAWholeNumberFrom\") : undefined}\n >\n <TextInput\n inputMode=\"numeric\"\n value={speakers}\n placeholder={msg(\"meetings.detailPage.auto\")}\n onChange={(event) => setSpeakers(event.target.value.replace(/[^0-9]/gu, \"\"))}\n className=\"max-w-24\"\n />\n </Field>\n ) : null}\n </FieldStack>\n </FormDialog>\n );\n}\n\nfunction VisibilityMenu({\n visibility,\n onChange,\n}: {\n visibility: RecordingVisibility;\n onChange: (visibility: RecordingVisibility) => void;\n}) {\n const msg = useOpenGeniText();\n const options: Array<{ value: RecordingVisibility; label: string; description: string }> = [\n {\n value: \"private\",\n label: msg(\"meetings.detailPage.onlyMe\"),\n description: msg(\"meetings.detailPage.onlyYouCanOpenIt\"),\n },\n {\n value: \"workspace\",\n label: msg(\"meetings.detailPage.workspace\"),\n description: msg(\"meetings.detailPage.everyoneInThisWorkspaceCan\"),\n },\n ];\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"rounded-[10px] pointer-coarse:h-11\"\n aria-label={msg(\"meetings.detailPage.whoCanSeeThisValue\", {\n value:\n visibility === \"private\"\n ? msg(\"meetings.detailPage.onlyMe\")\n : msg(\"meetings.detailPage.workspace\"),\n })}\n >\n {visibility === \"private\" ? (\n <LockIcon aria-hidden=\"true\" />\n ) : (\n <GlobeIcon aria-hidden=\"true\" />\n )}\n {visibility === \"private\"\n ? msg(\"meetings.detailPage.onlyMe\")\n : msg(\"meetings.detailPage.workspace\")}\n <ChevronDownIcon aria-hidden=\"true\" className=\"text-fg-subtle\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-64\">\n {options.map((option) => (\n <DropdownMenuItem\n key={option.value}\n onSelect={() => {\n if (option.value !== visibility) onChange(option.value);\n }}\n className=\"items-start\"\n >\n <span className=\"grid min-w-0 flex-1 gap-0.5\">\n <span className=\"text-sm leading-5 text-fg\">{option.label}</span>\n <span className=\"text-xs leading-4.5 text-fg-muted\">{option.description}</span>\n </span>\n {option.value === visibility ? (\n <CheckIcon aria-hidden=\"true\" className=\"mt-0.5 text-brand\" />\n ) : null}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\n/** A transcript version's model and the provider it runs on, by name. */\ntype ModelAbout = {\n modelName: string;\n providerName: string;\n funding: string;\n /** The deployment offers no other model. */\n pinned: boolean;\n};\n\nconst SPINNER = (\n <LoaderCircleIcon aria-hidden=\"true\" className=\"size-4 animate-spin motion-reduce:animate-none\" />\n);\n\n/** What fixes a failed transcript, besides transcribing it again from the dialog. */\ntype TranscriptFixes = {\n /** The models this workspace can transcribe with, to pick the direct fix from. */\n models: readonly RecordingTranscriptionModel[];\n /** Transcribe it now with another model, the one-click fix. */\n onTranscribeWith: (model: RecordingTranscriptionModel) => Promise<void>;\n /** Opens where credits are bought; absent when this person can't buy them. */\n onOpenBilling?: (() => void) | undefined;\n /** Opens where models are connected; absent when this person can't connect them. */\n onConnectModels?: (() => void) | undefined;\n};\n\n/**\n * A failed transcript's actions: one direct fix (another model that works\n * here, else adding credits or connecting a model), then Transcribe again,\n * which tries once more with any model once the cause is fixed.\n */\nfunction FailedTranscriptActions({\n version,\n about,\n fixes,\n onRetry,\n}: {\n version: RecordingTranscriptVersion | null;\n about: ModelAbout | null;\n fixes: TranscriptFixes;\n onRetry: () => void;\n}) {\n const msg = useOpenGeniText();\n const [running, setRunning] = useState(false);\n const code = version?.errorCode ?? null;\n const switchTo = transcriptFixModel(code, version, fixes.models);\n const connect =\n !switchTo &&\n (code === \"missing_provider_key\" || code === \"provider_unauthorized\") &&\n about?.funding !== \"deployment\"\n ? fixes.onConnectModels\n : undefined;\n const billing = !switchTo && transcriptNeedsCredits(code) ? fixes.onOpenBilling : undefined;\n return (\n <span className=\"flex flex-wrap gap-2\">\n {switchTo ? (\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={running}\n onClick={() => {\n setRunning(true);\n void fixes\n .onTranscribeWith(switchTo)\n .catch((error: unknown) => {\n toast.error(msg(\"meetings.detailPage.couldnTStartTranscribing\"), {\n description: errorText(error),\n });\n })\n .finally(() => setRunning(false));\n }}\n >\n {running ? SPINNER : null}\n {msg(\"meetings.detailPage.transcribeWithModel\", { modelName: switchTo.name })}\n </Button>\n ) : billing ? (\n <Button type=\"button\" size=\"sm\" onClick={billing}>\n <CreditCardIcon aria-hidden=\"true\" />\n {msg(\"meetings.detailPage.addCredits\")}\n </Button>\n ) : connect ? (\n <Button type=\"button\" size=\"sm\" onClick={connect}>\n {msg(\"meetings.detailPage.connectAModel\")}\n </Button>\n ) : null}\n <Button type=\"button\" size=\"sm\" variant=\"outline\" disabled={running} onClick={onRetry}>\n {msg(\"meetings.detailPage.transcribeAgain\")}\n </Button>\n </span>\n );\n}\n\n/** Why an upload failed, in the words of a transcript failure when it has the same cause. */\nfunction uploadFailureText(\n failure: { code: string; message: string } | null,\n msg: OpenGeniText,\n): string {\n if (!failure) return msg(\"meetings.detailPage.theAudioCouldnTBeUploaded\");\n if (transcriptNeedsCredits(failure.code)) return transcriptErrorText(failure.code, msg);\n // The notice's title already says the upload failed; the server's reason\n // reads as the first sentence of its text.\n const reason = failure.message.trim();\n if (!reason) return msg(\"meetings.detailPage.theAudioCouldnTBeUploaded\");\n return /[.!?]$/.test(reason) ? reason : `${reason}.`;\n}\n\nfunction PhaseNotice({\n recording,\n recorder,\n here,\n recordingElsewhere,\n modelOf,\n fixes,\n onRetry,\n}: {\n recording: Recording;\n recorder: MeetingRecorder | null;\n /** What this device's recorder knows about the meeting; null when it isn't recording it. */\n here: MeetingHereStatus | null;\n /** It's captured on another device with the live preview on. */\n recordingElsewhere: boolean;\n /** The version's model and its provider, when the workspace's list has it. */\n modelOf: (version: RecordingTranscriptVersion) => ModelAbout | null;\n fixes: TranscriptFixes;\n onRetry: () => void;\n}) {\n const msg = useOpenGeniText();\n const phase = meetingPhase(recording);\n if (phase.kind === \"uploading\" && recorder && (here === \"recording\" || here === \"paused\")) {\n return <RecordingBar recorder={recorder} />;\n }\n if (phase.kind === \"uploading\" && here === \"waiting_for_connection\") {\n return (\n <Notice tone=\"waiting\" live=\"polite\">\n {msg(\"meetings.recorderPanel.notUploadingNoConnectionThe\")}\n </Notice>\n );\n }\n if (phase.kind === \"uploading\" && recorder && here === \"upload_failed\") {\n // The audio stays on this device: once the cause is fixed, the same upload carries on.\n return (\n <Notice\n tone=\"failed\"\n title={msg(\"meetings.detailPage.theUploadDidnTFinish\")}\n live=\"polite\"\n actionLayout=\"responsive\"\n action={\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n // The uploader holding it was closed: reloading starts a new one.\n if (!recorder.retryUpload(recording.id)) {\n toast.error(msg(\"meetings.detailPage.couldnTTryAgainReload\"));\n }\n }}\n >\n {msg(\"meetings.detailPage.tryAgain\")}\n </Button>\n }\n >\n {msg(\"meetings.detailPage.uploadFailureKeptHere\", {\n reason: uploadFailureText(meetingUploadFailure(recorder, recording.id), msg),\n })}\n </Notice>\n );\n }\n if (phase.kind === \"uploading\" && here === \"uploading\") {\n return (\n <Notice tone=\"waiting\" icon={SPINNER} live=\"polite\">\n {msg(\"meetings.detailPage.uploadingFromThisDevice\")}\n </Notice>\n );\n }\n if (phase.kind === \"uploading\" && here !== \"transcribing\") {\n // Nothing on this device can move it along: say where the audio is and what finishes it.\n return recordingElsewhere ? (\n <Notice\n tone=\"waiting\"\n icon={SPINNER}\n title={msg(\"meetings.detailPage.notFinishedYet\")}\n live=\"polite\"\n >\n {msg(\"meetings.detailPage.itSStillBeingRecorded\")}\n </Notice>\n ) : (\n <Notice tone=\"waiting\" title={msg(\"meetings.detailPage.notFinishedYet\")} live=\"polite\">\n {msg(\"meetings.detailPage.theAudioIsOnThe\")}\n </Notice>\n );\n }\n if (phase.kind === \"transcribing\" || phase.kind === \"uploading\") {\n return (\n <Notice tone=\"waiting\" icon={SPINNER} live=\"polite\">\n {transcribingText(recording.durationMilliseconds, msg)}\n </Notice>\n );\n }\n if (phase.kind === \"failed\") {\n const about = phase.version ? modelOf(phase.version) : null;\n return (\n <Notice\n tone=\"failed\"\n title={msg(\"meetings.detailPage.theTranscriptFailed\")}\n actionLayout=\"responsive\"\n action={\n <FailedTranscriptActions\n version={phase.version}\n about={about}\n fixes={fixes}\n onRetry={onRetry}\n />\n }\n >\n {transcriptErrorText(phase.version?.errorCode ?? null, msg, about)}\n </Notice>\n );\n }\n return null;\n}\n\nfunction versionLine(\n version: RecordingTranscriptVersion,\n modelName: (version: RecordingTranscriptVersion) => string,\n msg: OpenGeniText = defaultText,\n): string {\n const parts = [\n msg(\"meetings.detailPage.versionVersionnumber\", { versionNumber: version.versionNumber }),\n modelName(version),\n ];\n if (version.state === \"queued\" || version.state === \"processing\")\n parts.push(msg(\"meetings.detailPage.transcribing\"));\n if (version.state === \"failed\") parts.push(msg(\"meetings.detailPage.failed\"));\n if (version.state === \"complete\" && version.languages.length > 0) {\n parts.push(version.languages.map((code) => languageName(code, msg.locale)).join(\", \"));\n }\n return parts.join(\" · \");\n}\n\n/**\n * A newer version than the one shown: still running, or failed. The current\n * transcript stays readable either way, so this is a quiet line, not a block.\n */\nfunction RerunNotice({\n versions,\n shownVersionNumber,\n modelName,\n modelOf,\n fixes,\n onRetry,\n}: {\n versions: readonly RecordingTranscriptVersion[];\n shownVersionNumber: number;\n modelName: (version: RecordingTranscriptVersion) => string;\n modelOf: (version: RecordingTranscriptVersion) => ModelAbout | null;\n fixes: TranscriptFixes;\n onRetry: () => void;\n}) {\n const msg = useOpenGeniText();\n const newest = versions.reduce<RecordingTranscriptVersion | null>(\n (best, entry) => (!best || entry.versionNumber > best.versionNumber ? entry : best),\n null,\n );\n if (!newest || newest.versionNumber <= shownVersionNumber) return null;\n if (newest.state === \"queued\" || newest.state === \"processing\") {\n return (\n <Notice tone=\"waiting\" icon={SPINNER} live=\"polite\">\n {msg(\"meetings.detailPage.transcribingAgainWithModelnameThis\", {\n modelName: modelName(newest),\n })}\n </Notice>\n );\n }\n if (newest.state === \"failed\") {\n return (\n <Notice\n tone=\"failed\"\n title={msg(\"meetings.detailPage.transcribingAgainFailed\")}\n actionLayout=\"responsive\"\n action={\n <FailedTranscriptActions\n version={newest}\n about={modelOf(newest)}\n fixes={fixes}\n onRetry={onRetry}\n />\n }\n >\n {msg(\"meetings.detailPage.transcripterrortextThisVersionIsUnchanged\", {\n transcriptErrorText: transcriptErrorText(newest.errorCode, msg, modelOf(newest)),\n })}\n </Notice>\n );\n }\n return null;\n}\n\n/** The meeting page's tabs. */\ntype MeetingTab = \"summary\" | \"transcript\" | \"notepad\";\n\n/** Summary when there are written notes to read, else Transcript. */\nexport function openingMeetingTab(notes: RecordingNote | null): MeetingTab {\n return notes?.body.trim() ? \"summary\" : \"transcript\";\n}\n\n/** One of the host's own lines about a meeting, such as its project. */\nexport type MeetingDetail = { id: string; label: string; content: ReactNode };\n\ntype MeetingDetailPageProps = {\n workspaceId: string;\n recordingId: string;\n viewerSubjectId: string;\n /** The reader's name, for the people list when they name a speaker as themselves. */\n viewerName?: string;\n /** The workspace recognizes people by voice, so speakers can be suggested and voices remembered. */\n voiceRecognition?: boolean;\n /** A recordings client to use instead of the app's, for previews. */\n recordings?: RecordingsClientOverride[\"recordings\"];\n onBack: () => void;\n /** Opens Meetings settings, where voice recognition is turned on. */\n onOpenSettings?: (() => void) | undefined;\n /**\n * Opens where this person adds credits, the fix a transcript refused for\n * credits offers when no other model works here. Omit it for someone who\n * can't buy credits.\n */\n onOpenBilling?: (() => void) | undefined;\n /**\n * Opens where models are connected, the fix for a transcript whose\n * provider isn't connected. Omit it for someone who can't connect one.\n */\n onConnectModels?: (() => void) | undefined;\n /**\n * The host's own lines about this meeting, shown first beside the\n * transcript, such as the project it belongs to.\n */\n details?: ((recording: Recording) => readonly MeetingDetail[]) | undefined;\n /**\n * The viewer's workspaces in this organization, their Personal workspace\n * marked, so they can choose where their own Only me meetings work\n * (\"Available in\"). Without it the page doesn't offer that choice.\n */\n reachWorkspaces?: readonly ReachWorkspace[] | undefined;\n /** The organization's name, for \"Available in\". */\n organizationName?: string | undefined;\n /** Opens a chat, such as the one whose agent wrote the notes. */\n onOpenChat?: ((sessionId: string) => void) | undefined;\n /**\n * Answers \"Ask about this meeting\", usually by starting a chat with the\n * meeting attached and the question as its first message. Without it the\n * page has no Ask input. Resolve false to keep the question in the input\n * when the host couldn't take it and has already said why.\n */\n onAsk?:\n | ((recordingId: string, question: string) => MeetingAskResult | Promise<MeetingAskResult>)\n | undefined;\n};\n\n/**\n * Each meeting starts fresh, even when the host keeps the page mounted and\n * only changes `recordingId`: its own opening tab, drafts and dialogs.\n */\nexport function MeetingDetailPage(props: MeetingDetailPageProps) {\n return (\n <MeetingsOverlayScope>\n <MeetingDetailPageForRecording key={props.recordingId} {...props} />\n </MeetingsOverlayScope>\n );\n}\n\nfunction MeetingDetailPageForRecording({\n workspaceId,\n recordingId,\n viewerSubjectId,\n viewerName,\n voiceRecognition = false,\n recordings: recordingsClient,\n onBack,\n onOpenSettings,\n onOpenBilling,\n onConnectModels,\n details,\n reachWorkspaces,\n organizationName,\n onOpenChat,\n onAsk,\n}: MeetingDetailPageProps) {\n const msg = useOpenGeniText();\n const override = { workspaceId, ...(recordingsClient ? { recordings: recordingsClient } : {}) };\n const meeting = useRecording(recordingId, override);\n const recording = meeting.recording;\n const version = recording?.transcript ?? null;\n const transcriptVersionId =\n version?.state === \"complete\"\n ? version.id\n : meeting.versions.find((candidate) => candidate.isCurrent && candidate.state === \"complete\")\n ?.id;\n const transcript = useTranscript(recordingId, {\n ...override,\n ...(transcriptVersionId ? { versionId: transcriptVersionId } : {}),\n refreshKey: transcriptVersionId ?? null,\n enabled: Boolean(transcriptVersionId),\n });\n // A person's own Only me meeting from another workspace of the organization\n // keeps its people and transcribers in the workspace that stores it.\n const home = { ...override, workspaceId: recording?.workspaceId ?? workspaceId };\n const people = useRecordingPeople(home);\n const models = useRecordingModels(home);\n const { client } = useRecordingsClient(override);\n const { recorder } = useMeetingRecorder();\n const online = useOnline();\n // The live preview, while a meeting is recorded and until its transcript is\n // ready: this browser's own recorder has it first; anyone else reads what\n // the recorder saved.\n const recordingHere = Boolean(recorder && recorder.recordingId === recordingId && recorder.live);\n const previewing =\n Boolean(recording?.tracks.some((track) => track.live)) &&\n !transcriptVersionId &&\n (recording?.state === \"capturing\" || recording?.state === \"processing\");\n const savedLive = useLiveTranscript(recordingId, {\n ...override,\n enabled: previewing && !recordingHere,\n });\n const player = useRef<MeetingPlayerHandle>(null);\n // The player's bar pins to the top while the page scrolls; pinned, it covers\n // the host scroller's top padding too (sticky-bar-edge.tsx).\n const [playerBar, setPlayerBar] = useState<HTMLDivElement | null>(null);\n const playerPinned = useStuckToTop(playerBar);\n const [position, setPosition] = useState(0);\n const [renaming, setRenaming] = useState(false);\n const [choosingReach, setChoosingReach] = useState(false);\n const [rerunning, setRerunning] = useState(false);\n const [deleting, setDeleting] = useState(false);\n const [namingFromAside, setNamingFromAside] = useState<string | null>(null);\n const [rememberingVoice, setRememberingVoice] = useState<RecordingPerson | null>(null);\n const notes = useRecordingNotes(recordingId, override);\n // The notes name a meeting nobody named: show that name once they arrive.\n // The name is written just after the notes, so it is read again shortly.\n const notesRevision = notes.notes?.revision ?? 0;\n const refreshMeeting = meeting.refresh;\n const awaitingName = Boolean(recording && recording.titleSource !== \"person\");\n const seenNotesRevision = useRef<number | null>(null);\n useEffect(() => {\n if (notes.loading) return;\n const seen = seenNotesRevision.current;\n seenNotesRevision.current = notesRevision;\n if (seen === null || seen === notesRevision || !awaitingName) return;\n void refreshMeeting();\n const again = window.setTimeout(() => void refreshMeeting(), 3_000);\n return () => window.clearTimeout(again);\n }, [notes.loading, notesRevision, awaitingName, refreshMeeting]);\n // Summary when the meeting has written notes, else Transcript: decided once\n // the notes load, so notes written later don't move the reader.\n const [openingTab, setOpeningTab] = useState<MeetingTab | null>(null);\n const [chosenTab, setChosenTab] = useState<MeetingTab | null>(null);\n if (openingTab === null && !notes.loading) {\n setOpeningTab(openingMeetingTab(notes.notes));\n }\n const tab = chosenTab ?? openingTab;\n // The ⌘K menu's \"Ask about this meeting\": the Ask field shows on Summary and\n // Transcript, so a question from the Notepad tab moves to Summary first.\n const [askRequest, setAskRequest] = useState<MeetingAskRequest | null>(null);\n const tabRef = useRef(tab);\n tabRef.current = tab;\n const askFromMenu = useCallback((question: string | null) => {\n if (tabRef.current === \"notepad\") setChosenTab(\"summary\");\n setAskRequest((current) => ({ question, nonce: (current?.nonce ?? 0) + 1 }));\n }, []);\n const recordingOnScreenHere =\n recording?.state === \"capturing\" &&\n [\"recording\", \"paused\"].includes(meetingHereStatus(recorder, recordingId, online) ?? \"\");\n useAnnounceMeetingOnScreen(\n useUiEventTarget(\"document\"),\n recordingId,\n onAsk && recording && !recordingOnScreenHere ? askFromMenu : null,\n );\n const slots = useMemo(() => speakerColorSlots(transcript.segments), [transcript.segments]);\n const mentionTracks = recording?.tracks;\n const mentions = useMemo(\n () =>\n meetingMentionResolver({\n speakers: transcript.speakers,\n tracks: mentionTracks ?? [],\n people: people.people,\n slots,\n msg,\n }),\n [transcript.speakers, mentionTracks, people.people, slots, msg],\n );\n\n const { sources, reload } = useTrackSources(recording, (trackNumber) =>\n client.getRecordingTrackAudio(workspaceId, recordingId, trackNumber),\n );\n\n const modelName = useCallback(\n (entry: RecordingTranscriptVersion) =>\n models.models.find(\n (candidate) => candidate.providerId === entry.providerId && candidate.model === entry.model,\n )?.name ?? entry.model,\n [models.models],\n );\n const modelOf = useCallback(\n (entry: RecordingTranscriptVersion): ModelAbout | null => {\n const found = models.models.find(\n (candidate) => candidate.providerId === entry.providerId && candidate.model === entry.model,\n );\n return found\n ? {\n modelName: found.name,\n providerName: found.providerName,\n funding: found.funding,\n pinned: models.pinned,\n }\n : null;\n },\n [models.models, models.pinned],\n );\n // A failed transcript's direct fix runs another model with this meeting's\n // own options; null language detects it, as Transcribe again does.\n const rerunMeeting = meeting.rerun;\n const shownTranscription = recording?.transcription;\n const fixes: TranscriptFixes = {\n models: models.models,\n onTranscribeWith: async (model) => {\n const { providerId: _provider, model: _model, ...options } = shownTranscription ?? {};\n await rerunMeeting({\n ...options,\n providerId: model.providerId,\n model: model.model,\n language: options.language ?? null,\n });\n },\n onOpenBilling,\n onConnectModels,\n };\n\n const createPerson = people.create;\n const { rememberVoice, forgetVoice } = people;\n const refreshTranscript = transcript.refresh;\n const rejectSuggestion = transcript.rejectSuggestion;\n const nameSpeaker = transcript.nameSpeaker;\n const transcriptSpeakers = transcript.speakers;\n const peopleList = people.people;\n // Naming reads the people list right after a person was created, before\n // the list has rerendered with them.\n const latestPeople = useRef(peopleList);\n latestPeople.current = peopleList;\n const createdPeople = useRef(new Map<string, RecordingPerson>());\n const offeredVoices = useRef(new Set<string>());\n // Without voice recognition a name is only for this meeting; say so once,\n // the first time someone is named here.\n const toldNotRemembered = useRef(false);\n const tellNotRemembered = useCallback(() => {\n if (voiceRecognition || toldNotRemembered.current) return;\n toldNotRemembered.current = true;\n toast(msg(\"meetings.detailPage.namesArenTSuggestedIn\"), {\n description: msg(\"meetings.detailPage.voiceRecognitionIsOffIn\"),\n ...(onOpenSettings\n ? { action: { label: msg(\"meetings.detailPage.settings\"), onClick: onOpenSettings } }\n : {}),\n });\n }, [msg, voiceRecognition, onOpenSettings]);\n const offerMyVoice = useCallback(\n (me: RecordingPerson) => {\n // Naming yourself is when remembering your voice makes sense.\n toast.success(msg(\"meetings.detailPage.namedYou\"), {\n // Long enough to read and decide; the speaker menu offers it later too.\n duration: 10_000,\n description: msg(\"meetings.detailPage.rememberYourVoiceAndLater\"),\n action: {\n label: msg(\"meetings.detailPage.rememberMyVoice\"),\n onClick: () =>\n void rememberVoice(me.id, \"self\").then(\n () => toast.success(msg(\"meetings.detailPage.yourVoiceWillBeRemembered\")),\n (error: unknown) =>\n toast.error(msg(\"meetings.detailPage.couldnTRememberYourVoice\"), {\n description: errorText(error),\n }),\n ),\n },\n });\n },\n [msg, rememberVoice],\n );\n // A name teaches nothing until the person's voice may be remembered, so\n // say so once per person, the first time they're named here. Another\n // member decides for themselves, so naming them offers nothing.\n const offerToRemember = useCallback(\n (personId: string) => {\n const person =\n latestPeople.current.find((candidate) => candidate.id === personId) ??\n createdPeople.current.get(personId);\n if (!person || person.voice || offeredVoices.current.has(person.id)) return;\n const self = Boolean(viewerSubjectId) && person.memberSubjectId === viewerSubjectId;\n if (person.memberSubjectId && !self) return;\n offeredVoices.current.add(person.id);\n if (self) {\n offerMyVoice(person);\n return;\n }\n toast.success(\n msg(\"meetings.detailPage.namedDisplayname\", { displayName: person.displayName }),\n {\n duration: 10_000,\n description: msg(\"meetings.detailPage.rememberTheirVoiceAndLater\"),\n action: {\n label: msg(\"meetings.detailPage.rememberVoice\"),\n onClick: () => setRememberingVoice(person),\n },\n },\n );\n },\n [msg, viewerSubjectId, offerMyVoice],\n );\n const actions: TranscriptActions = useMemo(\n () => ({\n nameSpeaker: async (label, name) => {\n await nameSpeaker(label, name);\n if (!name) return;\n if (!voiceRecognition) tellNotRemembered();\n else if (\"personId\" in name) offerToRemember(name.personId);\n },\n viewerSubjectId,\n nameSelf: async (label: string) => {\n const me =\n peopleList.find((person) => person.memberSubjectId === viewerSubjectId) ??\n (await createPerson({\n displayName: viewerName ?? msg(\"meetings.detailPage.me\"),\n memberSubjectId: viewerSubjectId,\n }));\n await nameSpeaker(label, { personId: me.id });\n if (!voiceRecognition) {\n tellNotRemembered();\n } else if (!me.voice) {\n offeredVoices.current.add(me.id);\n offerMyVoice(me);\n }\n },\n rejectSuggestion: async (label: string) => {\n const suggested = speakerIsSuggested(label, transcriptSpeakers);\n await rejectSuggestion(label);\n const personId = suggested?.personId;\n toast.success(\n suggested\n ? msg(\"meetings.detailPage.suggestionDismissed\")\n : msg(\"meetings.detailPage.leftUnnamed\"),\n suggested && personId\n ? {\n description: msg(\"meetings.detailPage.thisSpeakerIsUnnamedAgain\"),\n // A mis-tap on \"Not them\" is easy; naming them puts it right.\n action: {\n label: msg(\"meetings.detailPage.undo\"),\n onClick: () =>\n void nameSpeaker(label, { personId }).catch((error: unknown) =>\n toast.error(msg(\"meetings.detailPage.couldnTNameThisSpeaker\"), {\n description: errorText(error),\n }),\n ),\n },\n }\n : undefined,\n );\n },\n moveSegment: transcript.moveSegment,\n editSegment: transcript.editSegment,\n createPerson: async (displayName: string) => {\n const person = await createPerson({ displayName });\n createdPeople.current.set(person.id, person);\n return person;\n },\n voices: voiceRecognition\n ? {\n viewerSubjectId,\n remember: (person) => {\n if (person.memberSubjectId !== viewerSubjectId) {\n setRememberingVoice(person);\n return;\n }\n void rememberVoice(person.id, \"self\").then(\n () => toast.success(msg(\"meetings.detailPage.yourVoiceWillBeRemembered\")),\n (error: unknown) =>\n toast.error(msg(\"meetings.detailPage.couldnTRememberYourVoice\"), {\n description: errorText(error),\n }),\n );\n },\n forget: async (person) => {\n await forgetVoice(person.id);\n // Forgetting also removes the names it suggested in this meeting.\n await refreshTranscript();\n toast.success(\n person.memberSubjectId === viewerSubjectId\n ? msg(\"meetings.detailPage.yourVoiceIsForgotten\")\n : msg(\"meetings.detailPage.displaynameSVoiceIsForgotten\", {\n displayName: person.displayName,\n }),\n );\n },\n }\n : null,\n }),\n [\n msg,\n nameSpeaker,\n rejectSuggestion,\n transcriptSpeakers,\n transcript.moveSegment,\n transcript.editSegment,\n createPerson,\n voiceRecognition,\n viewerSubjectId,\n viewerName,\n peopleList,\n tellNotRemembered,\n offerMyVoice,\n offerToRemember,\n rememberVoice,\n forgetVoice,\n refreshTranscript,\n ],\n );\n\n if (!recording) {\n return (\n <DetailPage back={{ label: msg(\"meetings.detailPage.meetings\"), onClick: onBack }}>\n {meeting.error ? (\n isNotFound(meeting.error) ? (\n <EmptyState\n variant=\"page\"\n icon={<AudioLinesIcon />}\n title={msg(\"meetings.detailPage.thisMeetingDoesnTExist\")}\n description={msg(\"meetings.detailPage.itMayHaveBeenDeleted\")}\n action={\n <Button type=\"button\" variant=\"outline\" onClick={onBack}>\n {msg(\"meetings.detailPage.backToMeetings\")}\n </Button>\n }\n className=\"pt-12\"\n />\n ) : (\n <ErrorMessage\n align=\"center\"\n title={msg(\"meetings.detailPage.couldnTLoadThisMeeting\")}\n details={[{ label: msg(\"meetings.detailPage.error\"), value: meeting.error.message }]}\n action={\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void meeting.refresh()}\n >\n {msg(\"meetings.detailPage.tryAgain\")}\n </Button>\n }\n >\n {msg(\"meetings.detailPage.checkYourConnectionThenTry\")}\n </ErrorMessage>\n )\n ) : (\n <div aria-busy=\"true\" className=\"grid gap-6\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-7 w-72\" />\n <Skeleton className=\"h-4 w-96 max-w-full\" />\n </div>\n <Skeleton className=\"h-12 w-full rounded-[14px]\" />\n <div className=\"space-y-3\">\n <Skeleton className=\"h-4 w-40\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-5/6\" />\n </div>\n <span className=\"sr-only\" role=\"status\">\n {msg(\"meetings.detailPage.loadingMeeting\")}\n </span>\n </div>\n )}\n </DetailPage>\n );\n }\n\n const owner = recording.ownerSubjectId === viewerSubjectId;\n // The owner's own Only me meeting, on a server that keeps where it works.\n const reachable =\n owner &&\n recording.visibility === \"private\" &&\n recording.purpose === \"meeting\" &&\n recording.reachWorkspaceIds !== undefined &&\n reachWorkspaces !== undefined;\n // The person recording, as the transcript will name their microphone.\n const ownerName =\n peopleList.find((person) => person.memberSubjectId === recording.ownerSubjectId)?.displayName ??\n (owner ? (viewerName ?? null) : null);\n const phase = meetingPhase(recording);\n // Only while the server still waits for audio: this device may know more.\n const here =\n recording.state === \"capturing\" ? meetingHereStatus(recorder, recording.id, online) : null;\n const capturingHere = here === \"recording\" || here === \"paused\";\n // Recording on this device: one page with the bar, the notepad and the live\n // preview. Once it stops (and everywhere else), Summary · Transcript · Notepad,\n // with this recorder's live text in Transcript until the transcript is ready.\n const tabbed = !capturingHere;\n const askable = Boolean(onAsk);\n const segments = transcript.segments;\n const speakerLabels = [...slots.keys()];\n const activeSegment = sources.length > 0 ? activeSegmentIndex(segments, position) : null;\n const showTranscript = Boolean(transcriptVersionId);\n const shownVersionNumber = version?.state === \"complete\" ? version.versionNumber : 0;\n const rerunPending = meeting.versions.some(\n (entry) =>\n entry.versionNumber > shownVersionNumber &&\n (entry.state === \"queued\" || entry.state === \"processing\"),\n );\n // Gone once retention deleted it, or when none was ever uploaded. Uploaded\n // audio without a playable copy yet (while it's transcribed, or after a\n // failure before that step) can still be transcribed again.\n const audioGone =\n recording.audioDeletedAt !== null ||\n (recording.state !== \"capturing\" &&\n !recording.tracks.some((track) => track.playable || track.chunkCount > 0));\n const canRerun = recording.state !== \"capturing\" && !audioGone && !rerunPending;\n // Pending before any transcript is done, it is the first one, not \"again\".\n const firstPending = rerunPending && shownVersionNumber === 0;\n const unnamedCount = speakerLabels.filter(\n (label) => !speakerIsNamed(label, transcript.speakers),\n ).length;\n const suggestedCount = speakerLabels.filter((label) =>\n speakerIsSuggested(label, transcript.speakers),\n ).length;\n // Speakers that still need someone to say who they are: unnamed, or a\n // name suggested from a voice that nobody has confirmed yet.\n const reviewLabels = speakerLabels.filter(\n (label) =>\n !speakerIsNamed(label, transcript.speakers) ||\n Boolean(speakerIsSuggested(label, transcript.speakers)),\n );\n\n const speakerButtons = (variant: \"list\" | \"chips\", labels: readonly string[] = speakerLabels) =>\n labels.map((label) => {\n const name = speakerDisplayName(label, transcript.speakers, recording.tracks, msg);\n const suggested = speakerIsSuggested(label, transcript.speakers);\n const unnamed = !speakerIsNamed(label, transcript.speakers);\n const menuLabel = suggested\n ? msg(\"meetings.detailPage.nameSuggestedFromTheirVoice\", { name: name })\n : unnamed\n ? msg(\"meetings.detailPage.nameNameThisSpeaker\", { name: name })\n : msg(\"meetings.detailPage.nameChangeWhoThisIs\", { name: name });\n return (\n <li key={label} className=\"min-w-0\">\n <SpeakerNameMenu\n label={label}\n displayName={name}\n speakers={transcript.speakers}\n people={people.people}\n actions={actions}\n onAddNew={setNamingFromAside}\n align={variant === \"list\" ? \"end\" : \"start\"}\n >\n {variant === \"list\" ? (\n <button\n type=\"button\"\n aria-label={menuLabel}\n className=\"-mx-1.5 flex w-[calc(100%+0.75rem)] min-w-0 items-center gap-2 rounded-[6px] px-1.5 py-1 text-left text-sm leading-5 text-fg transition-colors duration-[120ms] hover:bg-hover data-[state=open]:bg-hover pointer-coarse:min-h-11\"\n >\n <SpeakerDot slot={slots.get(label)} />\n <span className=\"grid min-w-0 flex-1\">\n <span className=\"truncate\">{name}</span>\n {suggested ? (\n <span className=\"truncate text-xs leading-4 text-fg-muted\">\n {msg(\"meetings.detailPage.suggestedFromTheirVoice\")}\n </span>\n ) : null}\n </span>\n <PencilIcon aria-hidden=\"true\" className=\"size-3.5 shrink-0 text-fg-subtle\" />\n </button>\n ) : (\n <button\n type=\"button\"\n aria-label={menuLabel}\n className={cn(\n \"flex max-w-52 min-w-0 items-center gap-2 rounded-full border border-border bg-surface px-3 py-1 text-sm leading-5 text-fg transition-colors duration-[120ms] hover:bg-hover data-[state=open]:bg-hover pointer-coarse:min-h-11\",\n (suggested || unnamed) && \"border-dashed border-border-strong\",\n )}\n >\n <SpeakerDot slot={slots.get(label)} />\n <span className=\"min-w-0 truncate\">\n {name}\n {suggested ? \"?\" : \"\"}\n </span>\n <PencilIcon aria-hidden=\"true\" className=\"size-3 shrink-0 text-fg-subtle\" />\n </button>\n )}\n </SpeakerNameMenu>\n {suggested && variant === \"list\" ? (\n <div className=\"mt-1 flex flex-wrap gap-1.5 pl-4\">\n <Button\n type=\"button\"\n size=\"xs\"\n className=\"pointer-coarse:h-11\"\n variant=\"outline\"\n aria-label={msg(\"meetings.detailPage.yesItSName\", { name: name })}\n onClick={() =>\n void actions\n .nameSpeaker(label, { personId: suggested.personId! })\n .catch((error: unknown) =>\n toast.error(msg(\"meetings.detailPage.couldnTConfirmThisName\"), {\n description: errorText(error),\n }),\n )\n }\n >\n <CheckIcon aria-hidden=\"true\" />\n {msg(\"meetings.detailPage.confirm\")}\n </Button>\n <Button\n type=\"button\"\n size=\"xs\"\n className=\"pointer-coarse:h-11\"\n variant=\"ghost\"\n aria-label={msg(\"meetings.detailPage.notName\", { name: name })}\n onClick={() =>\n void actions.rejectSuggestion(label).catch((error: unknown) =>\n toast.error(msg(\"meetings.detailPage.couldnTTurnDownThis\"), {\n description: errorText(error),\n }),\n )\n }\n >\n {msg(\"meetings.detailPage.notThem\")}\n </Button>\n </div>\n ) : null}\n </li>\n );\n });\n const reviewLine =\n reviewLabels.length === 0\n ? null\n : unnamedCount > 0 && suggestedCount > 0\n ? suggestedCount === 1\n ? msg(\"meetings.detailPage.whoSpokeSpeakersToNameOneName\", {\n count: unnamedCount,\n suggestedCount: suggestedCount,\n })\n : msg(\"meetings.detailPage.whoSpokeSpeakersToNameNames\", {\n count: unnamedCount,\n suggestedCount: suggestedCount,\n })\n : unnamedCount > 0\n ? msg(\"meetings.detailPage.whoSpokeSpeakersHaveNoName\", { count: unnamedCount })\n : msg(\"meetings.detailPage.whoSpokeNamesWereSuggested\", { count: suggestedCount });\n\n const update = async (\n request: Parameters<typeof meeting.update>[0],\n failure: string,\n ): Promise<void> => {\n try {\n await meeting.update(request);\n } catch (error) {\n toast.error(failure, { description: errorText(error) });\n throw error;\n }\n };\n\n const shownTitle = meetingTitle(recording, msg);\n const header = (\n <DetailPageHeader\n title={shownTitle}\n tabs={\n !tabbed ? undefined : tab === null ? (\n <Skeleton className=\"h-9 w-64 rounded-[10px]\" />\n ) : (\n <SegmentedControl\n aria-label={msg(\"meetings.detailPage.show\")}\n value={tab}\n onValueChange={setChosenTab}\n options={[\n { value: \"summary\", label: msg(\"meetings.detailPage.summary\") },\n { value: \"transcript\", label: msg(\"meetings.detailPage.transcript\") },\n { value: \"notepad\", label: msg(\"meetings.notes.notepad\") },\n ]}\n />\n )\n }\n meta={\n <DetailMeta>\n {formatAbsoluteTime(recording.startedAt, { text: msg })}\n {recording.durationMilliseconds > 0\n ? formatDuration(recording.durationMilliseconds, msg)\n : null}\n {speakerLabels.length > 0\n ? msg(\"meetings.detailPage.countSpeakers\", { count: speakerLabels.length })\n : null}\n {!owner && recording.visibility === \"workspace\"\n ? msg(\"meetings.detailPage.sharedWithTheWorkspace\")\n : null}\n {recording.sourceWorkspace\n ? msg(\"meetings.detailPage.onlyMeRecordedIn\", {\n workspace: recording.sourceWorkspace.name,\n })\n : null}\n </DetailMeta>\n }\n actions={\n <>\n {owner && !recording.sourceWorkspace ? (\n <VisibilityMenu\n visibility={recording.visibility}\n onChange={(visibility) =>\n void update({ visibility }, msg(\"meetings.detailPage.couldnTChangeWhoCan\")).then(\n () =>\n toast.success(\n visibility === \"workspace\"\n ? msg(\"meetings.detailPage.sharedWithTheWorkspace\")\n : msg(\"meetings.detailPage.onlyYouCanSeeThis\"),\n ),\n () => undefined,\n )\n }\n />\n ) : null}\n <MoreMenu label={msg(\"meetings.detailPage.moreActionsForTitle\", { title: shownTitle })}>\n <DropdownMenuItem onSelect={() => setRenaming(true)}>\n <PencilIcon aria-hidden=\"true\" />\n {msg(\"meetings.detailPage.rename\")}\n </DropdownMenuItem>\n {reachable ? (\n <DropdownMenuItem onSelect={() => setChoosingReach(true)}>\n <LayersIcon aria-hidden=\"true\" />\n {msg(\"meetings.detailPage.availableInMenu\")}\n </DropdownMenuItem>\n ) : null}\n {recording.state !== \"capturing\" ? (\n <DropdownMenuItem disabled={!canRerun} onSelect={() => setRerunning(true)}>\n <RefreshCwIcon aria-hidden=\"true\" />\n {rerunPending && !firstPending\n ? msg(\"meetings.detailPage.transcribingAgain\")\n : msg(\"meetings.detailPage.transcribeAgain\")}\n </DropdownMenuItem>\n ) : null}\n {owner ? (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem variant=\"destructive\" onSelect={() => setDeleting(true)}>\n <Trash2Icon aria-hidden=\"true\" />\n {msg(\"meetings.detailPage.deleteMeeting\")}\n </DropdownMenuItem>\n </>\n ) : null}\n </MoreMenu>\n </>\n }\n />\n );\n\n const hostDetails = details?.(recording) ?? [];\n const aside =\n showTranscript || meeting.versions.length > 0 || hostDetails.length > 0 ? (\n <DetailAside label={msg(\"meetings.detailPage.aboutThisTranscript\")}>\n {hostDetails.map((detail) => (\n <DetailAsideItem key={detail.id} label={detail.label}>\n {detail.content}\n </DetailAsideItem>\n ))}\n {speakerLabels.length > 0 ? (\n <DetailAsideItem label={msg(\"meetings.detailPage.speakers\")}>\n <div className=\"grid w-full min-w-0 gap-1\">\n <ul className=\"grid w-full min-w-0 gap-1\">{speakerButtons(\"list\")}</ul>\n {canRerun ? (\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"xs\"\n onClick={() => setRerunning(true)}\n className=\"h-auto w-fit px-0 text-fg-muted pointer-coarse:h-11\"\n >\n {msg(\"meetings.detailPage.wrongNumberOfSpeakers\")}\n </Button>\n ) : null}\n </div>\n </DetailAsideItem>\n ) : null}\n {meeting.versions.length > 0 ? (\n <DetailAsideItem label={msg(\"meetings.detailPage.transcript\")}>\n <div className=\"grid w-full min-w-0 gap-2\">\n {meeting.versions.length > 1 ? (\n <NativeSelect\n options={meeting.versions.map((entry) => ({\n value: entry.id,\n label: versionLine(entry, modelName, msg),\n disabled: entry.state !== \"complete\",\n }))}\n value={transcriptVersionId ?? meeting.versions[0]!.id}\n onValueChange={(versionId) =>\n void meeting.setCurrentVersion(versionId).catch((error: unknown) =>\n toast.error(msg(\"meetings.detailPage.couldnTSwitchVersions\"), {\n description: errorText(error),\n }),\n )\n }\n size=\"sm\"\n />\n ) : (\n <span className=\"text-sm leading-5 text-fg\">\n {versionLine(meeting.versions[0]!, modelName, msg)}\n </span>\n )}\n {phase.kind === \"failed\" || firstPending ? null : (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setRerunning(true)}\n disabled={!canRerun}\n className=\"w-fit rounded-[10px] pointer-coarse:h-11\"\n >\n {rerunPending ? SPINNER : <RefreshCwIcon aria-hidden=\"true\" />}\n {rerunPending\n ? msg(\"meetings.detailPage.transcribingAgain\")\n : msg(\"meetings.detailPage.transcribeAgain\")}\n </Button>\n )}\n </div>\n </DetailAsideItem>\n ) : null}\n </DetailAside>\n ) : undefined;\n\n // What the Transcript shows: who still needs a name, then the transcript,\n // or why there isn't one yet.\n const transcriptBody = (\n <>\n {showTranscript && reviewLabels.length > 0 ? (\n // Beside the speakers card, the speakers still to review sit at\n // the top of the transcript, where the reader starts. Only the outer\n // wrapper hides, so no display class competes with the container query.\n <div className=\"mb-5 @max-[620px]/detail:hidden\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"text-sm leading-5 text-fg-muted\">{reviewLine}</p>\n <ul\n aria-label={msg(\"meetings.detailPage.speakersToReview\")}\n className=\"flex flex-wrap gap-2\"\n >\n {speakerButtons(\"chips\", reviewLabels)}\n </ul>\n </div>\n </div>\n ) : null}\n {showTranscript && speakerLabels.length > 0 ? (\n // Only while the speakers card sits below the transcript. The\n // wrapper carries no display class, so the container query wins.\n <div className=\"mb-5 @[620px]/detail:hidden\">\n <div className=\"grid gap-2\">\n <ul aria-label={msg(\"meetings.detailPage.speakers\")} className=\"flex flex-wrap gap-2\">\n {speakerButtons(\"chips\")}\n </ul>\n {reviewLine ? (\n <p className=\"text-xs leading-4.5 text-fg-muted\">\n {msg(\"meetings.detailPage.reviewlineTapADashedName\", {\n reviewLine: reviewLine,\n })}\n </p>\n ) : null}\n </div>\n </div>\n ) : null}\n {!showTranscript && (previewing || recordingHere) ? (\n <div className=\"grid gap-3\">\n <p className=\"text-sm leading-5 text-fg-muted\">\n <span className=\"mr-2 inline-flex rounded-full border border-border px-1.5 text-xs leading-4 font-medium text-fg-label\">\n {msg(\"meetings.detailPage.preview\")}\n </span>\n {recording.state === \"capturing\" && here !== \"transcribing\"\n ? msg(\"meetings.detailPage.whatSSaidSoFar\")\n : msg(\"meetings.detailPage.whatWasSaidAsIt\")}\n </p>\n {recordingHere && recorder?.live ? (\n <LiveTranscript\n heading={false}\n lines={recorderLiveLines(recorder)}\n partials={recorder.live.map((track) => ({\n trackNumber: track.trackNumber,\n text: track.partial,\n }))}\n tracks={recorder.tracks}\n speakerName={(trackNumber) => liveSpeakerName(recorder, trackNumber, msg, ownerName)}\n status={liveStatus(recorder.live, msg)}\n empty={msg(\"meetings.detailPage.listeningWhatSSaidShows\")}\n />\n ) : (\n <LiveTranscript\n heading={false}\n lines={savedLive.segments}\n tracks={recording.tracks}\n speakerName={(trackNumber) => {\n const source = defaultSpeakerName(`track-${trackNumber}`, recording.tracks, msg);\n return (\n ownerLiveLaneName(recording.tracks, trackNumber, ownerName ?? source, msg) ??\n source\n );\n }}\n status={\n savedLive.error\n ? { text: msg(\"meetings.detailPage.canTLoadThePreview\"), tone: \"waiting\" }\n : null\n }\n empty={\n recording.state === \"capturing\"\n ? msg(\"meetings.detailPage.nothingSaidYetTextShows\")\n : msg(\"meetings.detailPage.noLiveTextWasSaved\")\n }\n />\n )}\n </div>\n ) : !showTranscript ? (\n <p className=\"text-sm leading-5 text-fg-muted\">\n {phase.kind === \"failed\"\n ? msg(\"meetings.detailPage.noTranscriptYet\")\n : phase.kind === \"no_transcript\"\n ? msg(\"meetings.detailPage.thisMeetingHasnTBeen\")\n : msg(\"meetings.detailPage.theTranscriptShowsHereWhen\")}\n </p>\n ) : transcript.loading && segments.length === 0 ? (\n <div className=\"space-y-3\" aria-busy=\"true\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-4/5\" />\n </div>\n ) : transcript.error && segments.length === 0 ? (\n <ErrorMessage\n title={msg(\"meetings.detailPage.couldnTLoadTheTranscript\")}\n details={[{ label: msg(\"meetings.detailPage.error\"), value: transcript.error.message }]}\n action={\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void transcript.refresh()}\n >\n {msg(\"meetings.detailPage.tryAgain\")}\n </Button>\n }\n >\n {msg(\"meetings.detailPage.checkYourConnectionThenTry\")}\n </ErrorMessage>\n ) : segments.length === 0 ? (\n <p className=\"text-sm leading-5 text-fg-muted\">\n {msg(\"meetings.detailPage.noSpeechWasFoundIn\")}\n </p>\n ) : (\n <MeetingTranscript\n segments={segments}\n speakers={transcript.speakers}\n tracks={recording.tracks}\n people={people.people}\n activeSegment={activeSegment}\n actions={actions}\n onSeek={sources.length > 0 ? (ms) => player.current?.playFrom(ms) : null}\n />\n )}\n </>\n );\n\n return (\n <DetailPage back={{ label: msg(\"meetings.detailPage.meetings\"), onClick: onBack }}>\n {header}\n <div className=\"mt-6 grid gap-4 empty:hidden\">\n <PhaseNotice\n recording={recording}\n recorder={recorder}\n here={here}\n recordingElsewhere={previewing && !recordingHere}\n modelOf={modelOf}\n fixes={fixes}\n onRetry={() => setRerunning(true)}\n />\n {phase.kind === \"ready\" ? (\n <RerunNotice\n versions={meeting.versions}\n shownVersionNumber={phase.version.versionNumber}\n modelName={modelName}\n modelOf={modelOf}\n fixes={fixes}\n onRetry={() => setRerunning(true)}\n />\n ) : null}\n {audioGone ? (\n <Notice tone=\"muted\">\n {recording.audioDeletedAt\n ? msg(\"meetings.detailPage.theAudioWasDeletedOn\", {\n formatAbsoluteTime: formatAbsoluteTime(recording.audioDeletedAt, { text: msg }),\n })\n : msg(\"meetings.detailPage.theAudioForThisMeeting\")}\n </Notice>\n ) : null}\n </div>\n {sources.length > 0 && !recording.audioDeletedAt ? (\n // A direct child of the page, so it stays in view through the whole transcript.\n <div ref={setPlayerBar} className=\"sticky top-0 z-10 -mx-1 mt-4 bg-bg px-1 pt-2 pb-2\">\n {playerPinned ? <StickyBarEdge edge=\"top\" /> : null}\n <MeetingPlayer\n ref={player}\n sources={sources}\n durationMilliseconds={recording.durationMilliseconds}\n onTime={setPosition}\n onSourceError={reload}\n />\n </div>\n ) : null}\n <DetailPageBody aside={aside}>\n {tabbed ? (\n // One column under the tabs; Ask keeps its draft across Summary and\n // Transcript. The Summary stays mounted while hidden, so an edit in\n // progress survives a look at the transcript.\n <div className=\"flex min-w-0 flex-col\">\n {tab === null ? (\n <DetailSection>\n <div aria-busy=\"true\" className=\"grid gap-3\">\n <Skeleton className=\"h-4 w-2/3\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-1/2\" />\n </div>\n </DetailSection>\n ) : (\n <>\n <div hidden={tab !== \"summary\"} data-meeting-tab=\"summary\">\n <DetailSection className={askable ? \"pb-2\" : undefined}>\n <MeetingSummary notes={notes} onOpenChat={onOpenChat} mentions={mentions} />\n </DetailSection>\n </div>\n {tab === \"transcript\" ? (\n <DetailSection key=\"transcript\" className={askable ? \"pb-2\" : undefined}>\n {transcriptBody}\n </DetailSection>\n ) : tab === \"notepad\" ? (\n <DetailSection key=\"notepad\">\n <MeetingNotepad notes={notes} />\n </DetailSection>\n ) : null}\n </>\n )}\n {askable && onAsk && tab !== \"notepad\" ? (\n <MeetingAsk\n onAsk={(question) => onAsk(recording.id, question)}\n request={askRequest}\n onRequestTaken={() => setAskRequest(null)}\n />\n ) : null}\n </div>\n ) : (\n // Recording here: the notepad first, then the live preview, as one page.\n <>\n <MeetingNotesSection\n notes={notes}\n capturing={recording.state === \"capturing\"}\n onOpenChat={onOpenChat}\n mentions={mentions}\n />\n <DetailSection title={msg(\"meetings.detailPage.transcript\")}>\n {transcriptBody}\n </DetailSection>\n </>\n )}\n </DetailPageBody>\n <RenameDialog\n open={renaming}\n title={shownTitle}\n onClose={() => setRenaming(false)}\n onRename={async (title) =>\n await update({ title }, msg(\"meetings.detailPage.couldnTRenameThisMeeting2\"))\n }\n />\n {reachable ? (\n <MeetingReachDialog\n open={choosingReach}\n recording={recording}\n hereId={workspaceId}\n workspaces={reachWorkspaces ?? []}\n organizationName={organizationName ?? msg(\"meetings.detailPage.thisOrganization\")}\n onClose={() => setChoosingReach(false)}\n onSave={async (reachWorkspaceIds, leavesHere) => {\n if (!leavesHere) {\n await meeting.update({ reachWorkspaceIds });\n return;\n }\n // It no longer works here: save without reading it back, then leave.\n await client.updateRecording(workspaceId, recording.id, { reachWorkspaceIds });\n toast.success(msg(\"meetings.detailPage.itNoLongerShowsHere\"));\n onBack();\n }}\n />\n ) : null}\n <TranscribeAgainDialog\n open={rerunning}\n recording={recording}\n models={models.models}\n defaultModel={models.defaultModel}\n onClose={() => setRerunning(false)}\n onRun={async (options) => {\n await meeting.rerun(options);\n toast.success(msg(\"meetings.detailPage.transcribingAgain2\"), {\n description: msg(\"meetings.detailPage.theNewVersionReplacesThis\"),\n });\n }}\n />\n <NewSpeakerNameDialog\n label={namingFromAside}\n displayName={\n namingFromAside\n ? speakerDisplayName(namingFromAside, transcript.speakers, recording.tracks, msg)\n : \"\"\n }\n actions={actions}\n onClose={() => setNamingFromAside(null)}\n />\n <ConfirmDialog\n open={rememberingVoice !== null}\n onOpenChange={(open) => {\n if (!open) setRememberingVoice(null);\n }}\n destructive={false}\n title={msg(\"meetings.detailPage.rememberValueSVoice\", {\n value: rememberingVoice?.displayName ?? msg(\"meetings.detailPage.their\"),\n })}\n description={msg(\"meetings.detailPage.onlyDoThisIfValue\", {\n value: rememberingVoice?.displayName ?? msg(\"meetings.detailPage.they\"),\n })}\n confirmLabel={msg(\"meetings.detailPage.theyAgreedRemember\")}\n pendingLabel={msg(\"meetings.detailPage.saving\")}\n onConfirm={async () => {\n const person = rememberingVoice;\n if (!person) return;\n try {\n await rememberVoice(person.id, \"attested\");\n toast.success(\n msg(\"meetings.detailPage.displaynameSVoiceWillBe\", {\n displayName: person.displayName,\n }),\n );\n } catch (error) {\n toast.error(msg(\"meetings.detailPage.couldnTRememberThisVoice\"), {\n description: errorText(error),\n });\n return false;\n }\n }}\n />\n <DeleteMeetingDialog\n recording={deleting ? { id: recording.id, title: shownTitle } : null}\n onClose={() => setDeleting(false)}\n onDelete={async () => await meeting.remove()}\n onDeleted={onBack}\n />\n </DetailPage>\n );\n}\n","/**\n * Plays a meeting's tracks together: the microphone and the shared audio are\n * separate files, so one control drives every <audio> element and keeps the\n * followers within a quarter second of the first track.\n */\nimport { useOpenGeniText } from \"../messages/runtime\";\nimport { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from \"react\";\nimport { PauseIcon, PlayIcon, RotateCcwIcon, RotateCwIcon } from \"lucide-react\";\n\nimport { Button } from \"../ui/button\";\nimport { cn } from \"../app/lib/utils\";\n\nimport { formatClock } from \"../recordings\";\n\nexport type MeetingPlayerHandle = {\n /** Jump to a moment and play from there. */\n playFrom: (milliseconds: number) => void;\n};\n\nexport type MeetingPlayerSource = { trackNumber: number; url: string };\n\nconst RATES = [1, 1.25, 1.5, 2] as const;\nconst MAX_DRIFT_SECONDS = 0.25;\nconst SKIP_SECONDS = 15;\n\nexport const MeetingPlayer = forwardRef<\n MeetingPlayerHandle,\n {\n sources: MeetingPlayerSource[];\n /** Known length, shown before the audio's own metadata loads. */\n durationMilliseconds: number;\n /** Called about four times a second while playing, and on every seek. */\n onTime?: ((milliseconds: number) => void) | undefined;\n /** A track's link expired or failed; the parent fetches fresh links. */\n onSourceError?: (() => void) | undefined;\n className?: string | undefined;\n }\n>(function MeetingPlayer({ sources, durationMilliseconds, onTime, onSourceError, className }, ref) {\n const msg = useOpenGeniText();\n const audioRefs = useRef<Map<number, HTMLAudioElement>>(new Map());\n const [playing, setPlaying] = useState(false);\n const [current, setCurrent] = useState(0);\n const [duration, setDuration] = useState(durationMilliseconds / 1000);\n const [rate, setRate] = useState<(typeof RATES)[number]>(1);\n const onTimeRef = useRef(onTime);\n onTimeRef.current = onTime;\n\n const elements = useCallback(\n () =>\n sources\n .map((source) => audioRefs.current.get(source.trackNumber))\n .filter((element): element is HTMLAudioElement => Boolean(element)),\n [sources],\n );\n const leader = useCallback(() => elements()[0] ?? null, [elements]);\n\n const seek = useCallback(\n (seconds: number) => {\n for (const element of elements()) element.currentTime = seconds;\n setCurrent(seconds);\n onTimeRef.current?.(seconds * 1000);\n },\n [elements],\n );\n const play = useCallback(() => {\n const lead = leader();\n for (const element of elements()) {\n if (lead && element !== lead) element.currentTime = lead.currentTime;\n void element.play().catch(() => setPlaying(false));\n }\n setPlaying(true);\n }, [elements, leader]);\n const pause = useCallback(() => {\n for (const element of elements()) element.pause();\n setPlaying(false);\n }, [elements]);\n\n useImperativeHandle(\n ref,\n () => ({\n playFrom: (milliseconds: number) => {\n seek(milliseconds / 1000);\n play();\n },\n }),\n [play, seek],\n );\n\n useEffect(() => {\n for (const element of elements()) element.playbackRate = rate;\n }, [elements, rate]);\n\n // Follow the leader: time display, transcript highlight and drift correction.\n useEffect(() => {\n const lead = leader();\n if (!lead) return;\n let last = 0;\n const update = () => {\n const now = performance.now();\n if (now - last < 240) return;\n last = now;\n setCurrent(lead.currentTime);\n onTimeRef.current?.(lead.currentTime * 1000);\n for (const element of elements()) {\n if (\n element !== lead &&\n Math.abs(element.currentTime - lead.currentTime) > MAX_DRIFT_SECONDS\n ) {\n element.currentTime = lead.currentTime;\n }\n }\n };\n const ended = () => pause();\n const metadata = () => {\n const longest = Math.max(\n ...elements().map((element) => (Number.isFinite(element.duration) ? element.duration : 0)),\n );\n if (longest > 0) setDuration(longest);\n };\n lead.addEventListener(\"timeupdate\", update);\n lead.addEventListener(\"ended\", ended);\n for (const element of elements()) element.addEventListener(\"loadedmetadata\", metadata);\n return () => {\n lead.removeEventListener(\"timeupdate\", update);\n lead.removeEventListener(\"ended\", ended);\n for (const element of elements()) element.removeEventListener(\"loadedmetadata\", metadata);\n };\n }, [elements, leader, pause]);\n\n const total = Math.max(duration, current);\n const progress = total > 0 ? Math.min(100, (current / total) * 100) : 0;\n const skip = (seconds: number) => seek(Math.min(Math.max(0, current + seconds), total));\n const skipClass =\n \"shrink-0 rounded-full text-fg-muted hover:text-fg pointer-coarse:size-11 max-sm:hidden\";\n return (\n <div\n className={cn(\n \"flex min-w-0 items-center gap-3 rounded-[14px] border border-border bg-surface px-3 py-2 max-sm:gap-2\",\n className,\n )}\n >\n {sources.map((source) => (\n <audio\n key={source.trackNumber}\n ref={(element) => {\n if (element) audioRefs.current.set(source.trackNumber, element);\n else audioRefs.current.delete(source.trackNumber);\n }}\n src={source.url}\n preload=\"metadata\"\n onError={() => onSourceError?.()}\n />\n ))}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => skip(-SKIP_SECONDS)}\n aria-label={msg(\"meetings.player.backCountSeconds\", { count: SKIP_SECONDS })}\n className={skipClass}\n >\n <RotateCcwIcon aria-hidden=\"true\" />\n </Button>\n <Button\n type=\"button\"\n size=\"icon-sm\"\n onClick={() => (playing ? pause() : play())}\n aria-label={playing ? msg(\"meetings.player.pause\") : msg(\"meetings.player.play\")}\n className=\"shrink-0 rounded-full pointer-coarse:size-11\"\n >\n {playing ? (\n <PauseIcon aria-hidden=\"true\" className=\"fill-current\" />\n ) : (\n <PlayIcon aria-hidden=\"true\" className=\"translate-x-px fill-current\" />\n )}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => skip(SKIP_SECONDS)}\n aria-label={msg(\"meetings.player.forwardCountSeconds\", { count: SKIP_SECONDS })}\n className={skipClass}\n >\n <RotateCwIcon aria-hidden=\"true\" />\n </Button>\n <span className=\"min-w-9 shrink-0 text-right text-xs leading-4 text-fg-muted tabular-nums\">\n {formatClock(current * 1000)}\n </span>\n {/* A native range for keyboard and screen readers, drawn with the palette. */}\n <span className=\"relative flex h-6 min-w-0 flex-1 items-center pointer-coarse:h-11\">\n <input\n type=\"range\"\n min={0}\n max={Math.max(1, total)}\n step={0.1}\n value={current}\n onChange={(event) => seek(Number(event.target.value))}\n aria-label={msg(\"meetings.player.position\")}\n aria-valuetext={msg(\"meetings.player.formatclockOfFormatclock2\", {\n formatClock: formatClock(current * 1000),\n formatClock2: formatClock(total * 1000),\n })}\n className=\"peer absolute inset-0 z-10 m-0 h-full w-full cursor-pointer opacity-0\"\n />\n <span aria-hidden=\"true\" className=\"h-1 w-full overflow-hidden rounded-full bg-surface-3\">\n <span className=\"block h-full rounded-full bg-brand\" style={{ width: `${progress}%` }} />\n </span>\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute top-1/2 size-3 -translate-x-1/2 -translate-y-1/2 rounded-full bg-brand shadow-[0_1px_2px_rgb(0_0_0/0.2)] ring-2 ring-surface transition-transform duration-[120ms] peer-hover:scale-125 peer-focus-visible:ring-4 peer-focus-visible:ring-ring/50\"\n style={{ left: `${progress}%` }}\n />\n </span>\n <span className=\"min-w-9 shrink-0 text-xs leading-4 text-fg-muted tabular-nums\">\n {formatClock(total * 1000)}\n </span>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setRate(RATES[(RATES.indexOf(rate) + 1) % RATES.length]!)}\n aria-label={msg(\"meetings.player.playbackSpeedRate\", { rate: rate })}\n title={msg(\"meetings.player.playbackSpeed\")}\n className=\"w-12 min-w-12 shrink-0 justify-center rounded-[8px] px-0 text-xs text-fg-muted tabular-nums pointer-coarse:h-11\"\n >\n {msg(\"meetings.player.rate\", { rate: rate })}\n </Button>\n </div>\n );\n});\n","/**\n * \"Ask about this meeting\": one line at the bottom of the Summary and\n * Transcript tabs. The host answers it, usually by starting a chat with the\n * meeting attached; the input clears once the host has taken the question.\n */\nimport { useOpenGeniText } from \"../messages/runtime\";\nimport { useEffect, useId, useRef, useState } from \"react\";\nimport { ArrowUpIcon, LoaderCircleIcon } from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\n\nimport { Button } from \"../ui/button\";\nimport { TextInput } from \"../ui/field\";\nimport { StickyBarEdge } from \"./sticky-bar-edge\";\n\n/** False when the host couldn't take the question and has already said why. */\nexport type MeetingAskResult = void | boolean;\n\n/**\n * A question from elsewhere in the app, such as the ⌘K menu: asked as if\n * typed here, or, with none, the cursor put in the field.\n */\nexport type MeetingAskRequest = { question: string | null; nonce: number };\n\nexport function MeetingAsk({\n onAsk,\n request = null,\n onRequestTaken,\n}: {\n /**\n * Takes the question. Resolving false keeps it in the input (the host has\n * said why); a rejection keeps it and says the chat couldn't start.\n */\n onAsk: (question: string) => MeetingAskResult | Promise<MeetingAskResult>;\n request?: MeetingAskRequest | null;\n /** The request has been taken, so it isn't acted on again. */\n onRequestTaken?: () => void;\n}) {\n const msg = useOpenGeniText();\n const id = useId();\n const inputRef = useRef<HTMLInputElement>(null);\n const [question, setQuestion] = useState(\"\");\n const [asking, setAsking] = useState(false);\n const trimmed = question.trim();\n const submit = async (text: string = trimmed) => {\n if (!text || asking) return;\n setAsking(true);\n try {\n if ((await onAsk(text)) !== false) setQuestion(\"\");\n } catch (error) {\n toast.error(msg(\"meetings.ask.couldNotAsk\"), {\n description: error instanceof Error ? userErrorText(error) : undefined,\n });\n } finally {\n setAsking(false);\n }\n };\n const submitRef = useRef(submit);\n submitRef.current = submit;\n const takenRef = useRef(onRequestTaken);\n takenRef.current = onRequestTaken;\n useEffect(() => {\n if (!request) return;\n takenRef.current?.();\n const text = request.question?.trim();\n if (text) {\n setQuestion(text);\n void submitRef.current(text);\n return;\n }\n inputRef.current?.focus({ preventScroll: true });\n inputRef.current?.scrollIntoView?.({ block: \"nearest\" });\n }, [request]);\n return (\n // Stays in reach at the bottom of the window while the tab scrolls. It ends\n // its column, so the page under it is covered all the way to the window's edge.\n <form\n aria-label={msg(\"meetings.ask.placeholder\")}\n className=\"sticky bottom-0 z-10 -mx-1 bg-bg px-1 pt-3 pb-4\"\n onSubmit={(event) => {\n event.preventDefault();\n void submit();\n }}\n >\n <StickyBarEdge edge=\"bottom\" />\n <div className=\"relative\">\n <label htmlFor={id} className=\"sr-only\">\n {msg(\"meetings.ask.placeholder\")}\n </label>\n <TextInput\n ref={inputRef}\n id={id}\n value={question}\n maxLength={4000}\n autoComplete=\"off\"\n disabled={asking}\n placeholder={msg(\"meetings.ask.placeholder\")}\n onChange={(event) => setQuestion(event.target.value)}\n className=\"h-11 rounded-[14px]! pr-12 shadow-og-sm\"\n />\n <Button\n type=\"submit\"\n size=\"icon-sm\"\n disabled={!trimmed || asking}\n aria-label={msg(\"meetings.ask.send\")}\n className=\"absolute top-1/2 right-1.5 size-8 -translate-y-1/2 rounded-[10px] pointer-coarse:size-9\"\n >\n {asking ? (\n <LoaderCircleIcon\n aria-hidden=\"true\"\n className=\"animate-spin motion-reduce:animate-none\"\n />\n ) : (\n <ArrowUpIcon aria-hidden=\"true\" />\n )}\n </Button>\n </div>\n </form>\n );\n}\n","import { useEffect, useState } from \"react\";\n\n/**\n * A sticky bar stops at its scroll container's padding. A host page that pads\n * its scroller (room for its own floating button, say) would show the page\n * scrolling past in the strip between the bar and the window's edge. This\n * paints the page background over that strip, as if the bar reached the edge.\n * It is a clipped shadow, so it adds no scroll length and catches no clicks.\n * Render it inside the sticky bar (which is positioned) and only while the bar\n * is pinned against `edge`; a bar that only ever ends its column can keep it.\n */\nexport function StickyBarEdge({ edge }: { edge: \"top\" | \"bottom\" }) {\n const down = edge === \"bottom\";\n return (\n <span\n aria-hidden\n data-og-sticky-edge={edge}\n className=\"pointer-events-none absolute inset-0\"\n style={{\n boxShadow: `0 ${down ? \"\" : \"-\"}50vh 0 50vh var(--color-bg)`,\n clipPath: down ? \"inset(0 0 -100vh 0)\" : \"inset(-100vh 0 0 0)\",\n }}\n />\n );\n}\n\n/** True while a sticky `top-0` bar is pinned to the top of its scroll container. */\nexport function useStuckToTop(bar: HTMLElement | null): boolean {\n const [stuck, setStuck] = useState(false);\n useEffect(() => {\n if (!bar) return;\n const scroller = scrollContainerOf(bar);\n let frame = 0;\n const measure = () => {\n frame = 0;\n setStuck(pinnedToTop(bar, scroller));\n };\n const schedule = () => {\n if (!frame) frame = requestAnimationFrame(measure);\n };\n measure();\n const target: HTMLElement | Window = scroller ?? window;\n target.addEventListener(\"scroll\", schedule, { passive: true });\n window.addEventListener(\"resize\", schedule);\n return () => {\n if (frame) cancelAnimationFrame(frame);\n target.removeEventListener(\"scroll\", schedule);\n window.removeEventListener(\"resize\", schedule);\n };\n }, [bar]);\n return stuck;\n}\n\n/** The nearest ancestor that scrolls vertically; null when the page itself scrolls. */\nexport function scrollContainerOf(node: HTMLElement): HTMLElement | null {\n for (let parent = node.parentElement; parent; parent = parent.parentElement) {\n if (parent === document.body || parent === document.documentElement) return null;\n const overflow = getComputedStyle(parent).overflowY;\n if (overflow === \"auto\" || overflow === \"scroll\" || overflow === \"overlay\") return parent;\n }\n return null;\n}\n\n/**\n * Pinned means the bar's top sits on the scroller's content edge (inside its\n * padding), where `top: 0` holds it; unpinned, it sits lower, in its own place.\n */\nexport function pinnedToTop(bar: HTMLElement, scroller: HTMLElement | null): boolean {\n const top = bar.getBoundingClientRect().top;\n if (!scroller) return top <= 1;\n const view = scroller.getBoundingClientRect();\n const padding = Number.parseFloat(getComputedStyle(scroller).paddingTop) || 0;\n return top <= view.top + scroller.clientTop + padding + 1;\n}\n","/**\n * Mentions in a meeting's written notes. The notes are Markdown, and an agent\n * (or a person) names someone with a link of exactly one of two forms:\n *\n * - `[Display name](speaker:<speakerLabel>)`: a voice in this meeting, such\n * as `speaker:speaker_0` or `speaker:track-0`.\n * - `[Display name](person:<personId>)`: someone in the people directory.\n *\n * Each shows as a small chip with the current name, so renaming a speaker or\n * a person updates the notes without rewriting them. A label or id this\n * meeting doesn't know shows the link text as plain text, never a link.\n */\nimport type { ReactNode } from \"react\";\nimport type { RecordingPerson, RecordingSpeaker, RecordingTrack } from \"@opengeni/contracts\";\n\nimport type { OpenGeniLinkRenderer } from \"../components/open-geni-links\";\nimport { createOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\nimport { speakerDisplayName } from \"../recordings\";\nimport { cn } from \"../app/lib/utils\";\n\nimport {\n SpeakerDot,\n speakerHueStyle,\n speakerTextClass,\n speakerTintClass,\n} from \"./meeting-transcript\";\n\nconst defaultText = createOpenGeniText();\n\nexport type MeetingMention =\n | { kind: \"speaker\"; label: string }\n | { kind: \"person\"; personId: string };\n\n/** Who a mention names now: the current name and, for a voice, its colour slot. */\nexport type ResolvedMeetingMention = { name: string; slot: number | undefined };\n\nexport type MeetingMentionResolver = (mention: MeetingMention) => ResolvedMeetingMention | null;\n\nconst MENTION_HREF = /^(speaker|person):(\\S+)$/u;\n\n/** The mention a link points at, or null when it is any other link. */\nexport function parseMeetingMention(href: string | null | undefined): MeetingMention | null {\n const match = MENTION_HREF.exec(href ?? \"\");\n if (!match) return null;\n let value = match[2]!;\n try {\n value = decodeURIComponent(value);\n } catch {\n // Not percent-encoded after all; keep it as written.\n }\n return match[1] === \"speaker\"\n ? { kind: \"speaker\", label: value }\n : { kind: \"person\", personId: value };\n}\n\n/**\n * Resolves mentions against this meeting: a speaker label it has (named or\n * heard in the transcript), or a person in the directory or named here.\n */\nexport function meetingMentionResolver({\n speakers,\n tracks,\n people,\n slots,\n msg = defaultText,\n}: {\n speakers: readonly RecordingSpeaker[];\n tracks: readonly RecordingTrack[];\n people: readonly RecordingPerson[];\n /** The transcript's colour slot per speaker label. */\n slots: ReadonlyMap<string, number>;\n msg?: OpenGeniText;\n}): MeetingMentionResolver {\n return (mention) => {\n if (mention.kind === \"speaker\") {\n const known =\n slots.has(mention.label) || speakers.some((speaker) => speaker.label === mention.label);\n if (!known) return null;\n return {\n name: speakerDisplayName(mention.label, speakers, tracks, msg),\n slot: slots.get(mention.label),\n };\n }\n // A person who spoke here takes that voice's colour.\n const voice = speakers.find((speaker) => speaker.personId === mention.personId);\n const slot = voice ? slots.get(voice.label) : undefined;\n const person = people.find((candidate) => candidate.id === mention.personId);\n if (person?.displayName.trim()) return { name: person.displayName, slot };\n if (voice?.name.trim()) return { name: voice.name, slot };\n return null;\n };\n}\n\n/**\n * What Copy looks at, in reading order: a fenced code block, a code span or\n * an image (each kept as written, as the page draws them literally), or a\n * mention `[text](speaker:…)` / `[text](person:…)`, with `\\]`-escaped\n * brackets in the text. A code span, like on the page, never crosses a blank\n * line.\n */\nconst COPY_SCAN =\n /^ {0,3}(?<mark>`{3,}|~{3,})[^\\n]*[\\s\\S]*?(?:\\n {0,3}\\k<mark>[`~]*[ \\t]*(?=\\n|(?![\\s\\S]))|(?![\\s\\S]))|(?<ticks>`+)(?:(?!\\n[ \\t]*\\n)[\\s\\S])*?\\k<ticks>(?!`)|!\\[(?:\\\\.|[^\\\\\\]])*\\]\\([^)]*\\)|\\[(?<text>(?:\\\\.|[^\\\\\\]])*)\\]\\((?<kind>speaker|person):(?<value>[^()\\s]+)\\)/gmu;\n\n/** Link text as it reads: Markdown escapes removed. */\nfunction unescapeLinkText(text: string): string {\n return text.replace(/\\\\([\\\\`*_{}[\\]()#+\\-.!|<>~])/gu, \"$1\");\n}\n\n/**\n * The notes as Markdown with each mention turned into the plain current\n * name (or its link text when this meeting doesn't know it), for copying.\n */\nexport function meetingNotesForCopy(markdown: string, resolve: MeetingMentionResolver): string {\n return markdown.replace(COPY_SCAN, (...args: unknown[]) => {\n const match = args[0] as string;\n const { text, kind, value } = args.at(-1) as Partial<Record<string, string>>;\n // Code and images stay as they are.\n if (text === undefined || kind === undefined || value === undefined) return match;\n const mention = parseMeetingMention(`${kind}:${value}`);\n const resolved = mention ? resolve(mention) : null;\n return resolved ? resolved.name : unescapeLinkText(text);\n });\n}\n\n/** A mention as a small inline chip: a voice in its colour, a person plain. */\nexport function MeetingMentionChip({\n mention,\n name,\n slot,\n}: {\n mention: MeetingMention;\n name: string;\n slot: number | undefined;\n}) {\n return (\n <span\n data-mention={mention.kind}\n className={cn(\n \"inline-flex max-w-full items-center gap-1 rounded-full px-1.5 align-baseline text-[0.93em] leading-[1.45] font-medium whitespace-nowrap\",\n slot === undefined\n ? \"bg-surface-2 text-fg\"\n : [speakerTintClass(slot), speakerTextClass(slot)],\n )}\n style={speakerHueStyle(slot)}\n >\n {slot !== undefined ? <SpeakerDot slot={slot} className=\"size-1.5\" /> : null}\n <span className=\"min-w-0 truncate\">{name}</span>\n </span>\n );\n}\n\n/**\n * Draws mention links as chips for {@link Markdown}'s `renderLink`, and any\n * mention this meeting doesn't know as its plain text. Other links fall\n * through to the default renderer.\n */\nexport function meetingMentionLinkRenderer(resolve: MeetingMentionResolver): OpenGeniLinkRenderer {\n return ({ href, children }): ReactNode | undefined => {\n const mention = parseMeetingMention(href);\n if (!mention) return undefined;\n const resolved = resolve(mention);\n if (!resolved) return <>{children}</>;\n return <MeetingMentionChip mention={mention} name={resolved.name} slot={resolved.slot} />;\n };\n}\n","/**\n * A meeting's notes: the written-up notes (summary, decisions, action items)\n * shown as Markdown with Edit, and the notepad people jot into while the\n * meeting is recorded, which saves as they type.\n *\n * The meeting page shows them as its Summary and Notepad tabs. While the\n * meeting is being recorded here they share one Notes section, notepad\n * first. Notes an agent wrote say so and link to its chat; mentions of\n * speakers and people show as chips (see ./meeting-mentions).\n */\nimport { useOpenGeniText } from \"../messages/runtime\";\nimport { useEffect, useId, useMemo, useRef, useState, type ComponentProps } from \"react\";\nimport { BotIcon, CheckIcon, CopyIcon, LoaderCircleIcon, PencilIcon } from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\nimport type { RecordingNote } from \"@opengeni/contracts\";\nimport { OpenGeniApiError } from \"@opengeni/sdk\";\nimport { Markdown } from \"../components/markdown\";\nimport {\n useRecordingNotes,\n type RecordingsClientOverride,\n type UseRecordingNotesResult,\n} from \"../recordings\";\nimport { copyTextToClipboard } from \"../lib/clipboard\";\nimport { Button } from \"../ui/button\";\nimport { DetailSection } from \"../ui/detail-sheet\";\nimport { TextArea } from \"../ui/field\";\nimport { Notice } from \"../ui/notice\";\nimport { formatAbsoluteTime } from \"../ui/relative-time\";\nimport { Skeleton } from \"../ui/skeleton\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\n\nimport {\n meetingMentionLinkRenderer,\n meetingNotesForCopy,\n type MeetingMentionResolver,\n} from \"./meeting-mentions\";\n\n/** How long typing pauses before the notepad saves. */\nexport const NOTEPAD_SAVE_DELAY_MS = 800;\n\nfunction isNotesChanged(error: unknown): boolean {\n return (\n error instanceof OpenGeniApiError &&\n error.status === 409 &&\n error.details?.code === \"notes_changed\"\n );\n}\n\nfunction errorText(error: unknown): string | undefined {\n return error instanceof Error ? userErrorText(error) : undefined;\n}\n\nfunction MeetingNotesContent({\n recordingId,\n recording: override,\n capturing,\n onOpenChat,\n}: {\n recordingId: string;\n recording: RecordingsClientOverride;\n /** The meeting is being recorded now, so the notepad comes first. */\n capturing: boolean;\n /** Opens the chat whose agent wrote the notes. */\n onOpenChat?: ((sessionId: string) => void) | undefined;\n}) {\n const notes = useRecordingNotes(recordingId, override);\n return <MeetingNotesSection notes={notes} capturing={capturing} onOpenChat={onOpenChat} />;\n}\n\n/** The Notes section over notes the page already loads: notepad and written notes together. */\nexport function MeetingNotesSection({\n notes,\n capturing,\n onOpenChat,\n mentions,\n}: {\n notes: UseRecordingNotesResult;\n /** The meeting is being recorded now, so the notepad comes first. */\n capturing: boolean;\n onOpenChat?: ((sessionId: string) => void) | undefined;\n /** Resolves speaker and person mentions in the written notes. */\n mentions?: MeetingMentionResolver | null | undefined;\n}) {\n const msg = useOpenGeniText();\n const [editing, setEditing] = useState(false);\n\n if (notes.loading && !notes.notes && !notes.notepad) {\n return (\n <DetailSection title={msg(\"meetings.notes.title\")}>\n <NotesSkeleton />\n </DetailSection>\n );\n }\n\n const written = (\n <WrittenNotes\n note={notes.notes}\n editing={editing}\n onEdit={() => setEditing(true)}\n onDone={() => setEditing(false)}\n save={(body) => notes.save(\"notes\", body)}\n refresh={notes.refresh}\n onOpenChat={onOpenChat}\n mentions={mentions}\n />\n );\n const notepad = (\n <Notepad\n note={notes.notepad}\n rows={capturing ? 6 : 3}\n // Alone under the Notes heading while recording, it needs no second heading.\n labelHidden={capturing && !notes.notes}\n save={(body) => notes.save(\"notepad\", body)}\n />\n );\n\n return (\n <DetailSection\n title={msg(\"meetings.notes.title\")}\n action={\n notes.notes && !editing ? (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => setEditing(true)}\n className=\"pointer-coarse:h-11\"\n >\n <PencilIcon aria-hidden=\"true\" />\n {msg(\"meetings.notes.edit\")}\n </Button>\n ) : undefined\n }\n >\n <div className=\"grid gap-6\">\n {capturing ? (\n <>\n {notepad}\n {notes.notes ? written : null}\n </>\n ) : (\n <>\n {written}\n {notepad}\n </>\n )}\n </div>\n </DetailSection>\n );\n}\n\nfunction NotesSkeleton() {\n return (\n <div aria-busy=\"true\" className=\"grid gap-2\">\n <Skeleton className=\"h-4 w-2/3\" />\n <Skeleton className=\"h-4 w-1/2\" />\n </div>\n );\n}\n\n/**\n * The Summary tab: the written notes as Markdown, who wrote them, Copy and\n * Edit. Mentions of speakers and people show as chips with current names.\n */\nexport function MeetingSummary({\n notes,\n onOpenChat,\n mentions,\n}: {\n notes: UseRecordingNotesResult;\n onOpenChat?: ((sessionId: string) => void) | undefined;\n mentions: MeetingMentionResolver | null;\n}) {\n const msg = useOpenGeniText();\n const [editing, setEditing] = useState(false);\n // A reload (such as after the window was hidden) never replaces an edit.\n if (notes.loading && !notes.notes && !editing) return <NotesSkeleton />;\n const note = notes.notes;\n const hasBody = Boolean(note?.body.trim());\n return (\n <div className=\"grid gap-4\">\n {note && hasBody && !editing ? (\n <div className=\"flex min-w-0 flex-wrap items-center justify-between gap-x-4 gap-y-1\">\n <NotesAttribution note={note} onOpenChat={onOpenChat} />\n <div className=\"ml-auto flex shrink-0 items-center gap-1\">\n <CopyNotesButton\n text={() => (mentions ? meetingNotesForCopy(note.body, mentions) : note.body)}\n />\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => setEditing(true)}\n className=\"pointer-coarse:h-11\"\n >\n <PencilIcon aria-hidden=\"true\" />\n {msg(\"meetings.notes.edit\")}\n </Button>\n </div>\n </div>\n ) : null}\n <WrittenNotes\n note={note}\n editing={editing}\n onEdit={() => setEditing(true)}\n onDone={() => setEditing(false)}\n save={(body) => notes.save(\"notes\", body)}\n refresh={notes.refresh}\n onOpenChat={onOpenChat}\n mentions={mentions}\n attribution={false}\n />\n </div>\n );\n}\n\n/** The Notepad tab: what people jot down, saved as they type. */\nexport function MeetingNotepad({ notes }: { notes: UseRecordingNotesResult }) {\n if (notes.loading && !notes.notepad) return <NotesSkeleton />;\n return (\n <Notepad\n note={notes.notepad}\n rows={10}\n labelHidden\n save={(body) => notes.save(\"notepad\", body)}\n />\n );\n}\n\nconst COPIED_MS = 1600;\n\n/** Copies the notes, then says Copied for a moment. */\nfunction CopyNotesButton({ text }: { text: () => string }) {\n const msg = useOpenGeniText();\n const [copied, setCopied] = useState(false);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(\n () => () => {\n if (timer.current) clearTimeout(timer.current);\n },\n [],\n );\n return (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={() =>\n void copyTextToClipboard(text()).then((ok) => {\n if (!ok) {\n toast.error(msg(\"meetings.notes.couldNotCopy\"));\n return;\n }\n setCopied(true);\n if (timer.current) clearTimeout(timer.current);\n timer.current = setTimeout(() => setCopied(false), COPIED_MS);\n })\n }\n className=\"pointer-coarse:h-11\"\n >\n {copied ? <CheckIcon aria-hidden=\"true\" /> : <CopyIcon aria-hidden=\"true\" />}\n <span aria-live=\"polite\">\n {copied ? msg(\"meetings.notes.copied\") : msg(\"meetings.notes.copy\")}\n </span>\n </Button>\n );\n}\n\n/** \"Written by an agent · time · Open the chat\", or \"Edited · time\". */\nfunction NotesAttribution({\n note,\n onOpenChat,\n}: {\n note: RecordingNote;\n onOpenChat?: ((sessionId: string) => void) | undefined;\n}) {\n const msg = useOpenGeniText();\n const sessionId = note.updatedBy.sessionId;\n return (\n <p className=\"flex flex-wrap items-center gap-x-2 gap-y-1 text-xs leading-4 text-fg-muted\">\n {sessionId ? (\n <>\n <BotIcon aria-hidden=\"true\" className=\"size-3.5\" />\n <span>\n {msg(\"meetings.notes.writtenByAgent\", {\n time: formatAbsoluteTime(note.updatedAt, { text: msg }),\n })}\n </span>\n {onOpenChat ? (\n <button\n type=\"button\"\n onClick={() => onOpenChat(sessionId)}\n className=\"font-medium text-fg-label underline-offset-2 hover:underline pointer-coarse:min-h-11\"\n >\n {msg(\"meetings.notes.openChat\")}\n </button>\n ) : null}\n </>\n ) : (\n <span>\n {msg(\"meetings.notes.edited\", {\n time: formatAbsoluteTime(note.updatedAt, { text: msg }),\n })}\n </span>\n )}\n </p>\n );\n}\n\nfunction WrittenNotes({\n note,\n editing,\n onEdit,\n onDone,\n save,\n refresh,\n onOpenChat,\n mentions,\n attribution = true,\n}: {\n note: RecordingNote | null;\n editing: boolean;\n onEdit: () => void;\n onDone: () => void;\n save: (body: string) => Promise<RecordingNote>;\n refresh: () => Promise<void>;\n onOpenChat?: ((sessionId: string) => void) | undefined;\n mentions?: MeetingMentionResolver | null | undefined;\n /** Say who wrote them under the notes; the Summary tab says it in its header. */\n attribution?: boolean;\n}) {\n const msg = useOpenGeniText();\n const [draft, setDraft] = useState(note?.body ?? \"\");\n const [saving, setSaving] = useState(false);\n const [changedMeanwhile, setChangedMeanwhile] = useState(false);\n const editorId = useId();\n const renderLink = useMemo(\n // Without a resolver, mentions read as their link text, never a dead link.\n () => meetingMentionLinkRenderer(mentions ?? (() => null)),\n [mentions],\n );\n\n useEffect(() => {\n // Start each edit from the notes as they are now.\n if (editing) {\n setDraft(note?.body ?? \"\");\n setChangedMeanwhile(false);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editing]);\n\n if (editing) {\n const submit = async () => {\n setSaving(true);\n try {\n await save(draft);\n onDone();\n toast.success(msg(\"meetings.notes.saved\"));\n } catch (error) {\n if (isNotesChanged(error)) {\n // Load theirs so a second Save replaces it knowingly.\n await refresh();\n setChangedMeanwhile(true);\n } else {\n toast.error(msg(\"meetings.notes.couldNotSave\"), { description: errorText(error) });\n }\n } finally {\n setSaving(false);\n }\n };\n return (\n <div className=\"grid gap-3\">\n <label htmlFor={editorId} className=\"sr-only\">\n {msg(\"meetings.notes.editorLabel\")}\n </label>\n <TextArea\n id={editorId}\n rows={10}\n mono\n autoFocus\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n placeholder={msg(\"meetings.notes.editorPlaceholder\")}\n className=\"max-h-[60vh]\"\n />\n {changedMeanwhile ? (\n <Notice tone=\"info\">{msg(\"meetings.notes.changedMeanwhile\")}</Notice>\n ) : null}\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={saving}\n onClick={() => void submit()}\n className=\"pointer-coarse:h-11\"\n >\n {saving ? <LoaderCircleIcon aria-hidden=\"true\" className=\"animate-spin\" /> : null}\n {changedMeanwhile ? msg(\"meetings.notes.saveAnyway\") : msg(\"meetings.notes.save\")}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n disabled={saving}\n onClick={onDone}\n className=\"pointer-coarse:h-11\"\n >\n {msg(\"meetings.notes.cancel\")}\n </Button>\n <span className=\"text-xs leading-4 text-fg-muted\">\n {msg(\"meetings.notes.markdownHint\")}\n </span>\n </div>\n </div>\n );\n }\n\n if (!note || !note.body.trim()) {\n return (\n <div className=\"grid justify-items-start gap-3\">\n <p className=\"text-sm leading-5 text-fg-muted\">{msg(\"meetings.notes.empty\")}</p>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={onEdit}\n className=\"pointer-coarse:h-11\"\n >\n <PencilIcon aria-hidden=\"true\" />\n {msg(\"meetings.notes.write\")}\n </Button>\n </div>\n );\n }\n\n return (\n <div className=\"grid gap-3\">\n <Markdown className=\"text-sm\" renderLink={renderLink}>\n {note.body}\n </Markdown>\n {attribution ? <NotesAttribution note={note} onOpenChat={onOpenChat} /> : null}\n </div>\n );\n}\n\ntype NotepadStatus = \"idle\" | \"saving\" | \"saved\" | \"failed\";\n\nfunction Notepad({\n note,\n rows,\n labelHidden = false,\n save,\n}: {\n note: RecordingNote | null;\n rows: number;\n /** A heading or tab above already names it. */\n labelHidden?: boolean;\n save: (body: string) => Promise<RecordingNote>;\n}) {\n const msg = useOpenGeniText();\n const id = useId();\n const [draft, setDraft] = useState(note?.body ?? \"\");\n const [status, setStatus] = useState<NotepadStatus>(\"idle\");\n // What the server last confirmed, and whether the reader has typed since.\n const saved = useRef(note?.body ?? \"\");\n const dirty = useRef(false);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const saveRef = useRef(save);\n saveRef.current = save;\n\n // Text saved elsewhere arrives while nobody is typing here.\n useEffect(() => {\n const body = note?.body ?? \"\";\n if (!dirty.current && body !== saved.current) {\n saved.current = body;\n setDraft(body);\n }\n }, [note?.body]);\n\n const flush = (body: string) => {\n if (timer.current) clearTimeout(timer.current);\n timer.current = null;\n if (body === saved.current) {\n dirty.current = false;\n return;\n }\n setStatus(\"saving\");\n void saveRef.current(body).then(\n () => {\n saved.current = body;\n dirty.current = false;\n setStatus(\"saved\");\n },\n () => setStatus(\"failed\"),\n );\n };\n\n // Leaving the page saves what was typed last.\n const latest = useRef(draft);\n latest.current = draft;\n useEffect(\n () => () => {\n if (timer.current) flush(latest.current);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n );\n\n const statusText = (\n <span role=\"status\" aria-live=\"polite\" className=\"text-xs leading-4 text-fg-muted\">\n {status === \"saving\"\n ? msg(\"meetings.notes.notepadSaving\")\n : status === \"saved\"\n ? msg(\"meetings.notes.notepadSaved\")\n : status === \"failed\"\n ? msg(\"meetings.notes.notepadFailed\")\n : null}\n </span>\n );\n\n return (\n <div className=\"grid gap-2\">\n {labelHidden ? (\n <label htmlFor={id} className=\"sr-only\">\n {msg(\"meetings.notes.notepad\")}\n </label>\n ) : (\n <div className=\"flex items-baseline justify-between gap-3\">\n <label htmlFor={id} className=\"text-sm leading-5 font-medium text-fg\">\n {msg(\"meetings.notes.notepad\")}\n </label>\n {statusText}\n </div>\n )}\n <TextArea\n id={id}\n rows={rows}\n value={draft}\n placeholder={msg(\"meetings.notes.notepadPlaceholder\")}\n onChange={(event) => {\n const body = event.target.value;\n setDraft(body);\n dirty.current = true;\n setStatus(\"idle\");\n if (timer.current) clearTimeout(timer.current);\n timer.current = setTimeout(() => flush(body), NOTEPAD_SAVE_DELAY_MS);\n }}\n onBlur={() => flush(draft)}\n />\n {labelHidden ? <div className=\"flex min-h-4 justify-end\">{statusText}</div> : null}\n {status === \"failed\" ? (\n <button\n type=\"button\"\n onClick={() => flush(draft)}\n className=\"w-fit text-xs leading-4 font-medium text-fg-label underline-offset-2 hover:underline pointer-coarse:min-h-11\"\n >\n {msg(\"meetings.notes.notepadRetry\")}\n </button>\n ) : null}\n </div>\n );\n}\n\nexport function MeetingNotes(props: ComponentProps<typeof MeetingNotesContent>) {\n return (\n <MeetingsOverlayScope>\n <MeetingNotesContent {...props} />\n </MeetingsOverlayScope>\n );\n}\n","// Workspace settings → General → Meetings: who sees new meetings, which\n// model transcribes them, whether an agent writes their notes, and whether\n// people are recognized by voice. All live under the workspace's\n// `recordings` settings, which a patch replaces as a whole.\nimport { useOpenGeniText, createOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\nimport { regionRestrictedText } from \"../inference-region\";\nimport { useState, type ComponentProps } from \"react\";\nimport { toast } from \"sonner\";\nimport { userErrorText } from \"../ui/api-error\";\n\nimport {\n type RecordingPerson,\n type RecordingRetention,\n type RecordingTranscriptionModel,\n type RecordingVisibility,\n type WorkspaceRecordingSettings,\n} from \"@opengeni/contracts\";\nimport {\n languageName,\n useRecordingModels,\n useRecordingPeople,\n type RecordingsClientOverride,\n} from \"../recordings\";\nimport { Button } from \"../ui/button\";\nimport { ConfirmDialog } from \"../ui/confirm-dialog\";\nimport { Section } from \"../ui/section\";\nimport { WordListRow } from \"../ui/word-list-row\";\nimport { SegmentedControl } from \"../ui/segmented-control\";\nimport { NativeSelect, type SelectOption } from \"../ui/select-menu\";\nimport { SettingRow, SettingRowLink } from \"../ui/setting-row\";\nimport { Switch } from \"../ui/switch\";\n\nimport { DETECT_LANGUAGE, meetingLanguageOptions } from \"./meeting-languages\";\nimport { MeetingsOverlayScope } from \"./overlay-scope\";\n\nconst defaultText = createOpenGeniText();\n\nconst DEFAULT = \"default\";\nconst KEEP = \"keep\";\n\nconst AUDIO_PERIODS = [0, 7, 30, 90, 365] as const;\nconst MEETING_PERIODS = [30, 90, 180, 365, 730] as const;\n\n/** What a model costs and who pays, beside its name in the picker. */\nexport function transcriptionModelMeta(\n entry: RecordingTranscriptionModel,\n msg: OpenGeniText = defaultText,\n): string {\n if (entry.funding === \"workspace_subscription\") return msg(\"meetings.settings.yourSubscription\");\n if (entry.usdPerHour !== null && entry.usdPerHour > 0) {\n return msg(\"meetings.settings.valuePerHour\", { value: entry.usdPerHour.toFixed(2) });\n }\n return entry.providerName;\n}\n\n/** Why a model can't be picked yet, and what makes it pickable. */\nexport function transcriptionModelUnavailableReason(\n entry: RecordingTranscriptionModel,\n msg: OpenGeniText = defaultText,\n): string {\n const regionRestricted = regionRestrictedText(msg, entry.unavailableReason);\n if (regionRestricted) return regionRestricted;\n const providerName = entry.providerName;\n switch (entry.funding) {\n case \"workspace_subscription\":\n return msg(\"meetings.settings.connectYourProvidernameFirst\", { providerName });\n case \"workspace_key\":\n return msg(\"meetings.settings.connectProvidernameFirst\", { providerName });\n case \"deployment\":\n return msg(\"meetings.settings.providernameIsnTAvailableHere\", { providerName });\n }\n}\n\n/**\n * \"Not supported in EU\" when no live model is available and the server\n * switched them off for the region, otherwise null.\n */\nexport function liveTranscriptRestriction(\n liveModels: readonly Pick<RecordingTranscriptionModel, \"available\" | \"unavailableReason\">[],\n msg: OpenGeniText = defaultText,\n): string | null {\n if (liveModels.some((entry) => entry.available)) return null;\n return regionRestrictedText(\n msg,\n liveModels.find((entry) => entry.unavailableReason)?.unavailableReason,\n );\n}\n\n/** \"30 days\", \"1 year\", \"2 years\". */\nexport function retentionPeriodName(days: number, msg: OpenGeniText = defaultText): string {\n if (days % 365 === 0) return msg(\"meetings.settings.countYears\", { count: days / 365 });\n return msg(\"meetings.settings.countDays\", { count: days });\n}\n\n/**\n * The confirmation for a retention change that deletes what's already\n * recorded, or null when the change deletes nothing sooner than before.\n */\nexport function retentionChangeWarning(\n before: RecordingRetention | undefined,\n after: RecordingRetention,\n msg: OpenGeniText = defaultText,\n): { title: string; description: string; confirmLabel: string } | null {\n const shorter = (previous: number | undefined, next: number | undefined) =>\n next !== undefined && (previous === undefined || next < previous);\n if (shorter(before?.transcriptDays, after.transcriptDays)) {\n const period = retentionPeriodName(after.transcriptDays!, msg);\n return {\n title: msg(\"meetings.settings.deleteMeetingsAfterPeriod\", { period: period }),\n description: msg(\"meetings.settings.meetingsRecordedMoreThanPeriod\", {\n period: period,\n }),\n confirmLabel: msg(\"meetings.settings.deleteOldMeetings\"),\n };\n }\n if (shorter(before?.audioDays, after.audioDays)) {\n const days = after.audioDays!;\n return {\n title:\n days === 0\n ? msg(\"meetings.settings.deleteAudioOnceTranscribed\")\n : msg(\"meetings.settings.deleteAudioAfterRetentionperiodname\", {\n retentionPeriodName: retentionPeriodName(days, msg),\n }),\n description:\n days === 0\n ? msg(\"meetings.settings.theAudioOfEveryTranscribed\")\n : msg(\"meetings.settings.theAudioOfMeetingsRecorded\", {\n retentionPeriodName: retentionPeriodName(days, msg),\n }),\n confirmLabel:\n days === 0\n ? msg(\"meetings.settings.deleteTranscribedAudio\")\n : msg(\"meetings.settings.deleteOldAudio\"),\n };\n }\n return null;\n}\n\n/** Who is looking at the settings, so they can agree to have their own voice remembered. */\nexport type MeetingSettingsViewer = { subjectId: string; name: string };\n\nfunction MeetingDefaultsViewContent({\n workspaceId,\n settings: current,\n personal,\n canManage,\n viewer,\n onConnectModels,\n onSave,\n recordings,\n}: {\n workspaceId: string;\n settings: WorkspaceRecordingSettings;\n personal: boolean;\n canManage: boolean;\n viewer: MeetingSettingsViewer;\n onConnectModels?: (() => void) | undefined;\n /** Saves the whole `recordings` settings; false when a newer change took over. */\n onSave: (next: WorkspaceRecordingSettings) => Promise<boolean>;\n /** A recordings client to use instead of the app's, for previews. */\n recordings?: RecordingsClientOverride[\"recordings\"];\n}) {\n const msg = useOpenGeniText();\n const models = useRecordingModels({ workspaceId, ...(recordings ? { recordings } : {}) });\n const [saving, setSaving] = useState(false);\n const reason = canManage ? undefined : msg(\"meetings.settings.onlyWorkspaceAdminsCanChange\");\n\n /** False when the change failed or a newer one took over. */\n async function save(next: WorkspaceRecordingSettings, success: string): Promise<boolean> {\n setSaving(true);\n try {\n const saved = await onSave(next);\n if (saved) toast.success(success);\n return saved;\n } catch {\n toast.error(msg(\"meetings.settings.couldnTUpdateMeetingSettings\"));\n return false;\n } finally {\n setSaving(false);\n }\n }\n\n const visibility: RecordingVisibility = current.defaultVisibility ?? \"private\";\n const chooseVisibility = (next: RecordingVisibility) => {\n if (next === visibility) return;\n const { defaultVisibility: _previous, ...rest } = current;\n void save(\n next === \"private\" ? rest : { ...rest, defaultVisibility: next },\n next === \"workspace\"\n ? msg(\"meetings.settings.newMeetingsAreSharedWith\")\n : msg(\"meetings.settings.newMeetingsArePrivate\"),\n );\n };\n\n const fallback = models.defaultModel;\n const fallbackName =\n models.models.find(\n (entry) => entry.providerId === fallback?.providerId && entry.model === fallback?.model,\n )?.name ?? null;\n const chosen = current.transcription\n ? `${current.transcription.providerId}/${current.transcription.model}`\n : DEFAULT;\n const modelOptions: SelectOption[] = [\n {\n value: DEFAULT,\n // A pinned deployment has only that model, so it is not a default.\n label: fallbackName\n ? models.pinned\n ? fallbackName\n : msg(\"meetings.settings.defaultFallbackname\", { fallbackName: fallbackName })\n : msg(\"meetings.settings.default\"),\n },\n ...models.models.map((entry) => ({\n value: `${entry.providerId}/${entry.model}`,\n label: entry.name,\n meta: transcriptionModelMeta(entry, msg),\n disabled: !entry.available,\n disabledReason: entry.available ? undefined : transcriptionModelUnavailableReason(entry, msg),\n })),\n ];\n const chooseModel = (value: string) => {\n if (value === chosen) return;\n const { transcription: _previous, ...rest } = current;\n const entry = models.models.find(\n (candidate) => `${candidate.providerId}/${candidate.model}` === value,\n );\n void save(\n entry\n ? { ...rest, transcription: { providerId: entry.providerId, model: entry.model } }\n : rest,\n entry\n ? msg(\"meetings.settings.newMeetingsUseName\", { name: entry.name })\n : msg(\"meetings.settings.newMeetingsUseTheDefault\"),\n );\n };\n const noneAvailable =\n !models.loading && !models.error && !models.models.some((entry) => entry.available);\n\n const language = current.language ?? DETECT_LANGUAGE;\n const chooseLanguage = (value: string) => {\n if (value === language) return;\n const { language: _previous, ...rest } = current;\n void save(\n value === DETECT_LANGUAGE ? rest : { ...rest, language: value },\n value === DETECT_LANGUAGE\n ? msg(\"meetings.settings.newMeetingsDetectTheirLanguage\")\n : msg(\"meetings.settings.newMeetingsAreTranscribedIn\", {\n languageName: languageName(value, msg.locale),\n }),\n );\n };\n\n const voiceprints = current.voiceprints === true;\n\n const keyterms = current.keyterms ?? [];\n const chooseKeyterms = (next: string[]) => {\n const { keyterms: _previous, ...rest } = current;\n void save(\n next.length > 0 ? { ...rest, keyterms: next } : rest,\n next.length > 0\n ? msg(\"meetings.settings.meetingsListenForTheseWords\")\n : msg(\"meetings.settings.meetingsListenForNoWords\"),\n );\n };\n const [confirmingOff, setConfirmingOff] = useState(false);\n const chooseVoiceprints = (next: boolean) => {\n if (next === voiceprints) return;\n if (!next) {\n setConfirmingOff(true);\n return;\n }\n void save(\n { ...current, voiceprints: true },\n msg(\"meetings.settings.peopleAreRecognizedByVoice\"),\n );\n };\n\n const liveTranscript = current.liveTranscript === true;\n const liveModel = models.liveModels[0] ?? null;\n const liveAvailable = models.liveModels.some((entry) => entry.available);\n const liveRestricted = liveTranscriptRestriction(models.liveModels, msg);\n const chooseLiveTranscript = (next: boolean) => {\n if (next === liveTranscript) return;\n const { liveTranscript: _previous, ...rest } = current;\n void save(\n next ? { ...rest, liveTranscript: true } : rest,\n next\n ? msg(\"meetings.settings.newMeetingsShowALive\")\n : msg(\"meetings.settings.newMeetingsDonTShow\"),\n );\n };\n\n // On unless turned off, so only `false` is ever saved.\n const autoSummary = current.autoSummary !== false;\n const chooseAutoSummary = (next: boolean) => {\n if (next === autoSummary) return;\n const { autoSummary: _previous, ...rest } = current;\n void save(\n next ? rest : { ...rest, autoSummary: false },\n next\n ? msg(\"meetings.settings.anAgentWritesTheNotes\")\n : msg(\"meetings.settings.meetingsNoLongerGetNotes\"),\n );\n };\n\n const retention = current.retention;\n const [pendingRetention, setPendingRetention] = useState<{\n next: RecordingRetention;\n success: string;\n warning: NonNullable<ReturnType<typeof retentionChangeWarning>>;\n } | null>(null);\n const saveRetention = (next: RecordingRetention, success: string) => {\n const { retention: _previous, ...rest } = current;\n const empty = next.audioDays === undefined && next.transcriptDays === undefined;\n return save(empty ? rest : { ...rest, retention: next }, success);\n };\n const chooseRetention = (field: \"audioDays\" | \"transcriptDays\", value: string) => {\n const days = value === KEEP ? undefined : Number(value);\n if (days === retention?.[field]) return;\n const next: RecordingRetention = {};\n const audioDays = field === \"audioDays\" ? days : retention?.audioDays;\n const transcriptDays = field === \"transcriptDays\" ? days : retention?.transcriptDays;\n if (transcriptDays !== undefined) next.transcriptDays = transcriptDays;\n // Audio never outlives its meeting; past that it simply goes with it.\n if (audioDays !== undefined && (transcriptDays === undefined || audioDays <= transcriptDays)) {\n next.audioDays = audioDays;\n }\n const success =\n field === \"audioDays\"\n ? days === undefined\n ? msg(\"meetings.settings.audioIsKeptAsLong\")\n : days === 0\n ? msg(\"meetings.settings.audioIsDeletedOnceThe\")\n : msg(\"meetings.settings.audioIsDeletedAfterRetentionperiodname\", {\n retentionPeriodName: retentionPeriodName(days, msg),\n })\n : days === undefined\n ? msg(\"meetings.settings.meetingsAreKeptUntilSomeone\")\n : msg(\"meetings.settings.meetingsAreDeletedAfterRetentionperiodname\", {\n retentionPeriodName: retentionPeriodName(days, msg),\n });\n const warning = retentionChangeWarning(retention, next, msg);\n if (warning) {\n setPendingRetention({ next, success, warning });\n return;\n }\n void saveRetention(next, success);\n };\n const periodOptions = (\n periods: readonly number[],\n selected: number | undefined,\n keepLabel: string,\n limit: number | undefined,\n ): SelectOption[] => {\n const days = [...new Set([...periods, ...(selected === undefined ? [] : [selected])])].sort(\n (a, b) => a - b,\n );\n return [\n { value: KEEP, label: keepLabel },\n ...days.map((day) => {\n const tooLong = limit !== undefined && day > limit;\n return {\n value: String(day),\n label:\n day === 0\n ? msg(\"meetings.settings.deleteOnceTranscribed\")\n : retentionPeriodName(day, msg),\n disabled: tooLong,\n disabledReason: tooLong\n ? msg(\"meetings.settings.meetingsAreDeletedAfterRetentionperiodname\", {\n retentionPeriodName: retentionPeriodName(limit, msg),\n })\n : undefined,\n };\n }),\n ];\n };\n\n return (\n <Section\n title={msg(\"meetings.settings.meetings\")}\n description={msg(\"meetings.settings.defaultsForNewMeetingsAnd\")}\n >\n {personal ? null : (\n <SettingRow\n label={msg(\"meetings.settings.whoSeesNewMeetings\")}\n description={\n visibility === \"workspace\"\n ? msg(\"meetings.settings.everyoneInThisWorkspaceCan\")\n : msg(\"meetings.settings.onlyThePersonWhoRecorded\")\n }\n controlWidth=\"auto\"\n control={\n <SegmentedControl\n size=\"sm\"\n value={visibility}\n onValueChange={(next) => chooseVisibility(next as RecordingVisibility)}\n options={[\n { value: \"private\", label: msg(\"meetings.settings.onlyMe\") },\n { value: \"workspace\", label: msg(\"meetings.settings.workspace\") },\n ].map((option) => ({\n ...option,\n disabled: saving || !canManage,\n ...(reason ? { disabledReason: reason } : {}),\n }))}\n />\n }\n />\n )}\n <SettingRow\n label={msg(\"meetings.settings.transcriptionModel\")}\n description={\n models.pinned\n ? msg(\"meetings.settings.turnsAMeetingSAudioPinned\")\n : msg(\"meetings.settings.turnsAMeetingSAudio\")\n }\n controlWidth=\"select\"\n hint={\n noneAvailable ? (\n onConnectModels ? (\n <SettingRowLink onClick={onConnectModels}>\n {msg(\"meetings.settings.connectATranscriptionProviderTo\")}\n </SettingRowLink>\n ) : (\n msg(\"meetings.settings.anOrganizationAdminNeedsTo\")\n )\n ) : undefined\n }\n control={\n <NativeSelect\n aria-label={msg(\"meetings.settings.transcriptionModel\")}\n options={modelOptions}\n value={chosen}\n onValueChange={chooseModel}\n loading={models.loading && models.models.length === 0}\n disabled={saving || !canManage || models.pinned}\n {...(models.pinned\n ? { disabledReason: msg(\"meetings.settings.thisDeploymentUsesOneModel\") }\n : reason\n ? { disabledReason: reason }\n : {})}\n />\n }\n />\n <SettingRow\n label={msg(\"meetings.settings.meetingLanguage\")}\n description={msg(\"meetings.settings.newMeetingsAreTranscribedIn2\")}\n controlWidth=\"select\"\n control={\n <NativeSelect\n aria-label={msg(\"meetings.settings.meetingLanguage\")}\n options={meetingLanguageOptions(language, undefined, msg)}\n value={language}\n onValueChange={chooseLanguage}\n disabled={saving || !canManage}\n {...(reason ? { disabledReason: reason } : {})}\n />\n }\n />\n <WordListRow\n words={keyterms}\n saving={saving}\n disabled={!canManage}\n disabledReason={reason}\n text={{\n label: msg(\"meetings.settings.wordsToListenFor\"),\n description: msg(\"meetings.settings.wordsToListenForDescription\"),\n placeholder: msg(\"meetings.settings.wordsToListenForPlaceholder\"),\n termTooLong: (term, max) =>\n msg(\"meetings.settings.wordTooLong\", { term, max: String(max) }),\n tooMany: (max) => msg(\"meetings.settings.tooManyWords\", { max: String(max) }),\n }}\n onChange={chooseKeyterms}\n />\n <SettingRow\n label={msg(\"meetings.settings.writeNotesAfterEachMeeting\")}\n description={msg(\"meetings.settings.whenATranscriptIsReady\")}\n control={\n <Switch\n aria-label={msg(\"meetings.settings.writeNotesAfterEachMeeting\")}\n checked={autoSummary}\n pending={saving}\n disabled={!canManage}\n {...(reason ? { disabledReason: reason } : {})}\n onCheckedChange={chooseAutoSummary}\n />\n }\n />\n {liveModel ? (\n <SettingRow\n label={msg(\"meetings.settings.liveTranscript\")}\n description={\n liveRestricted ??\n msg(\"meetings.settings.showsWhatSSaidWhile\", {\n value:\n liveModel.usdPerHour !== null\n ? msg(\"meetings.settings.providernameChargesAboutValuePer\", {\n providerName: liveModel.providerName,\n value: liveModel.usdPerHour.toFixed(2),\n })\n : \"\",\n })\n }\n hint={\n !models.loading && !liveAvailable && !liveRestricted ? (\n onConnectModels ? (\n <SettingRowLink onClick={onConnectModels}>\n {msg(\"meetings.settings.connectProvidernameToShowA\", {\n providerName: liveModel.providerName,\n })}\n </SettingRowLink>\n ) : (\n msg(\"meetings.settings.anOrganizationAdminNeedsTo2\", {\n providerName: liveModel.providerName,\n })\n )\n ) : undefined\n }\n control={\n <Switch\n aria-label={msg(\"meetings.settings.liveTranscript\")}\n checked={liveTranscript && !liveRestricted}\n pending={saving}\n disabled={!canManage || liveRestricted !== null}\n // The description already says \"Not supported in EU\".\n {...(!liveRestricted && reason ? { disabledReason: reason } : {})}\n onCheckedChange={chooseLiveTranscript}\n />\n }\n />\n ) : null}\n <SettingRow\n label={msg(\"meetings.settings.recognizePeopleByVoice\")}\n description={\n voiceprints\n ? msg(\"meetings.settings.suggestsNamesForSpeakersIt\")\n : msg(\"meetings.settings.suggestsNamesForSpeakersIt2\")\n }\n control={\n <Switch\n aria-label={msg(\"meetings.settings.recognizePeopleByVoice\")}\n checked={voiceprints}\n pending={saving}\n disabled={!canManage}\n {...(reason ? { disabledReason: reason } : {})}\n onCheckedChange={chooseVoiceprints}\n />\n }\n />\n {voiceprints ? (\n <VoiceRows\n workspaceId={workspaceId}\n viewer={viewer}\n {...(recordings ? { recordings } : {})}\n />\n ) : null}\n <SettingRow\n label={msg(\"meetings.settings.keepMeetings\")}\n description={msg(\"meetings.settings.countedFromWhenAMeeting\")}\n controlWidth=\"select\"\n control={\n <NativeSelect\n aria-label={msg(\"meetings.settings.keepMeetings\")}\n options={periodOptions(\n MEETING_PERIODS,\n retention?.transcriptDays,\n msg(\"meetings.settings.untilSomeoneDeletesThem\"),\n undefined,\n )}\n value={\n retention?.transcriptDays === undefined ? KEEP : String(retention.transcriptDays)\n }\n onValueChange={(value) => chooseRetention(\"transcriptDays\", value)}\n disabled={saving || !canManage}\n {...(reason ? { disabledReason: reason } : {})}\n />\n }\n />\n <SettingRow\n label={msg(\"meetings.settings.keepAudio\")}\n description={msg(\"meetings.settings.deletingTheAudioKeepsThe\")}\n controlWidth=\"select\"\n control={\n <NativeSelect\n aria-label={msg(\"meetings.settings.keepAudio\")}\n options={periodOptions(\n AUDIO_PERIODS,\n retention?.audioDays,\n msg(\"meetings.settings.asLongAsTheMeeting\"),\n retention?.transcriptDays,\n )}\n value={retention?.audioDays === undefined ? KEEP : String(retention.audioDays)}\n onValueChange={(value) => chooseRetention(\"audioDays\", value)}\n disabled={saving || !canManage}\n {...(reason ? { disabledReason: reason } : {})}\n />\n }\n />\n <ConfirmDialog\n open={pendingRetention !== null}\n onOpenChange={(open) => {\n if (!open) setPendingRetention(null);\n }}\n title={pendingRetention?.warning.title ?? \"\"}\n description={pendingRetention?.warning.description ?? \"\"}\n confirmLabel={pendingRetention?.warning.confirmLabel ?? \"\"}\n pendingLabel={msg(\"meetings.settings.saving\")}\n onConfirm={async () => {\n if (!pendingRetention) return false;\n return await saveRetention(pendingRetention.next, pendingRetention.success);\n }}\n />\n <ConfirmDialog\n open={confirmingOff}\n onOpenChange={setConfirmingOff}\n title={msg(\"meetings.settings.stopRecognizingPeopleByVoice\")}\n description={msg(\"meetings.settings.everyVoiceRememberedInThis\")}\n confirmLabel={msg(\"meetings.settings.turnOffAndForgetVoices\")}\n pendingLabel={msg(\"meetings.settings.forgetting\")}\n onConfirm={async () => {\n const { voiceprints: _previous, ...rest } = current;\n return await save(rest, msg(\"meetings.settings.voicesForgottenPeopleArenT\"));\n }}\n />\n </Section>\n );\n}\n\n/**\n * \"Your voice\": each member decides for themselves. Agreeing lets Opengeni\n * learn the voice from meetings where they're named as a speaker.\n */\nfunction VoiceRows({\n workspaceId,\n viewer,\n recordings,\n}: {\n workspaceId: string;\n viewer: MeetingSettingsViewer;\n recordings?: RecordingsClientOverride[\"recordings\"];\n}) {\n const msg = useOpenGeniText();\n const people = useRecordingPeople({ workspaceId, ...(recordings ? { recordings } : {}) });\n const [busy, setBusy] = useState(false);\n const me: RecordingPerson | null =\n people.people.find((person) => person.memberSubjectId === viewer.subjectId) ?? null;\n const voice = me?.voice ?? null;\n\n async function run(work: () => Promise<unknown>, success: string, failure: string) {\n setBusy(true);\n try {\n await work();\n toast.success(success);\n } catch (error) {\n toast.error(failure, {\n description: error instanceof Error ? userErrorText(error) : undefined,\n });\n } finally {\n setBusy(false);\n }\n }\n\n const remember = () =>\n void run(\n async () => {\n const person =\n me ??\n (await people.create({ displayName: viewer.name, memberSubjectId: viewer.subjectId }));\n await people.rememberVoice(person.id, \"self\");\n },\n msg(\"meetings.settings.yourVoiceWillBeRemembered\"),\n msg(\"meetings.settings.couldnTRememberYourVoice\"),\n );\n const forget = () =>\n void run(\n async () => {\n if (me) await people.forgetVoice(me.id);\n },\n msg(\"meetings.settings.yourVoiceIsForgotten\"),\n msg(\"meetings.settings.couldnTForgetYourVoice\"),\n );\n\n const others = people.people\n .filter((person) => person.voice && person.id !== me?.id)\n .sort((left, right) => left.displayName.localeCompare(right.displayName));\n const forgetOther = (person: RecordingPerson) =>\n void run(\n async () => await people.forgetVoice(person.id),\n msg(\"meetings.settings.displaynameSVoiceIsForgotten\", { displayName: person.displayName }),\n msg(\"meetings.settings.couldnTForgetThisVoice\"),\n );\n\n return (\n <>\n <SettingRow\n label={msg(\"meetings.settings.yourVoice\")}\n description={\n voice\n ? voice.learned\n ? msg(\"meetings.settings.rememberedMeetingsSuggestYourName\")\n : msg(\"meetings.settings.youAgreedOpengeniLearnsYour\")\n : msg(\"meetings.settings.letsMeetingsSuggestYourName\")\n }\n controlWidth=\"auto\"\n control={\n voice ? (\n <Button type=\"button\" size=\"sm\" variant=\"outline\" disabled={busy} onClick={forget}>\n {msg(\"meetings.settings.forgetMyVoice\")}\n </Button>\n ) : (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n disabled={busy || people.loading}\n onClick={remember}\n >\n {msg(\"meetings.settings.rememberMyVoice\")}\n </Button>\n )\n }\n />\n <SettingRow\n label={msg(\"meetings.settings.rememberedVoices\")}\n description={\n others.length === 0\n ? msg(\"meetings.settings.nobodyElseYetPeopleCan\")\n : msg(\"meetings.settings.peopleWhoseVoicesSuggestNames\")\n }\n controlWidth=\"auto\"\n />\n {others.length > 0 ? (\n <ul aria-label={msg(\"meetings.settings.rememberedVoices\")} className=\"grid gap-1 pb-2\">\n {others.map((person) => (\n <li key={person.id} className=\"flex min-w-0 items-center gap-3 py-1\">\n <span className=\"grid min-w-0 flex-1\">\n <span className=\"truncate text-sm leading-5 text-fg\">{person.displayName}</span>\n <span className=\"truncate text-xs leading-4 text-fg-muted\">\n {person.voice?.consent === \"self\"\n ? person.voice?.learned\n ? msg(\"meetings.settings.agreedForThemselves\")\n : msg(\"meetings.settings.agreedForThemselvesNotHeard\")\n : person.voice?.learned\n ? msg(\"meetings.settings.someoneConfirmedTheyAgreed\")\n : msg(\"meetings.settings.someoneConfirmedTheyAgreedNot\")}\n </span>\n </span>\n {person.memberSubjectId ? (\n <span className=\"shrink-0 text-xs leading-4 text-fg-muted\">\n {msg(\"meetings.settings.onlyTheyCanForgetIt\")}\n </span>\n ) : (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n disabled={busy}\n aria-label={msg(\"meetings.settings.forgetDisplaynameSVoice\", {\n displayName: person.displayName,\n })}\n onClick={() => forgetOther(person)}\n >\n {msg(\"meetings.settings.forget\")}\n </Button>\n )}\n </li>\n ))}\n </ul>\n ) : null}\n </>\n );\n}\n\nexport function MeetingDefaultsView(props: ComponentProps<typeof MeetingDefaultsViewContent>) {\n return (\n <MeetingsOverlayScope>\n <MeetingDefaultsViewContent {...props} />\n </MeetingsOverlayScope>\n );\n}\n"],"mappings":"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","names":["useEffect","useId","useMemo","useRef","useState","ChevronDownIcon","PencilIcon","toast","useEffect","useMemo","useRef","useState","useRef","useState","Fragment","jsx","useState","useRef","Fragment","jsx","jsxs","defaultText","useMemo","useRef","useState","useEffect","jsxs","jsx","Fragment","defaultText","Fragment","jsx","jsxs","defaultText","useState","useEffect","useRef","useId","toast","PencilIcon","useMemo","ChevronDownIcon","useCallback","useEffect","useMemo","useRef","useState","AudioLinesIcon","toast","jsx","toast","Fragment","jsx","jsxs","useState","useEffect","useCallback","useMemo","useRef","AudioLinesIcon","useCallback","useEffect","useMemo","useRef","useState","AudioLinesIcon","CheckIcon","ChevronDownIcon","LoaderCircleIcon","LockIcon","PencilIcon","Trash2Icon","toast","useCallback","useEffect","useRef","useState","PauseIcon","PlayIcon","jsx","jsxs","MeetingPlayer","useRef","useState","useCallback","useEffect","PauseIcon","PlayIcon","useEffect","useId","useRef","useState","toast","useEffect","useState","jsx","jsx","jsxs","useId","useRef","useState","toast","useEffect","Fragment","jsx","jsxs","defaultText","useEffect","useId","useMemo","useRef","useState","CheckIcon","LoaderCircleIcon","PencilIcon","toast","Fragment","jsx","jsxs","useState","PencilIcon","useRef","useEffect","toast","CheckIcon","useId","useMemo","LoaderCircleIcon","Fragment","jsx","jsxs","defaultText","errorText","useState","useMemo","useRef","useEffect","useCallback","LockIcon","ChevronDownIcon","CheckIcon","LoaderCircleIcon","toast","AudioLinesIcon","PencilIcon","Trash2Icon","useState","toast","Fragment","jsx","jsxs","defaultText","useState","toast"]}
|