@arbidocs/blocks 0.5.91 → 0.5.92
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ConnectedCallDock-PJE7EZ6T.js → ConnectedCallDock-H5ABOXNR.js} +13 -13
- package/dist/{ConnectedCallDock-PJE7EZ6T.js.map → ConnectedCallDock-H5ABOXNR.js.map} +1 -1
- package/dist/{ConnectedCallDock-ZRSZYSLO.cjs → ConnectedCallDock-XF56C2JA.cjs} +22 -22
- package/dist/{ConnectedCallDock-ZRSZYSLO.cjs.map → ConnectedCallDock-XF56C2JA.cjs.map} +1 -1
- package/dist/{ConnectedCallRoom-XK2RPNO6.cjs → ConnectedCallRoom-EEI2ZVTS.cjs} +14 -14
- package/dist/{ConnectedCallRoom-XK2RPNO6.cjs.map → ConnectedCallRoom-EEI2ZVTS.cjs.map} +1 -1
- package/dist/{ConnectedCallRoom-S7DO2MP6.js → ConnectedCallRoom-N6DUEV4S.js} +13 -13
- package/dist/{ConnectedCallRoom-S7DO2MP6.js.map → ConnectedCallRoom-N6DUEV4S.js.map} +1 -1
- package/dist/{ConnectedMailInviteCard-YYPLRL6G.js → ConnectedMailInviteCard-2TXUPVV7.js} +4 -4
- package/dist/{ConnectedMailInviteCard-YYPLRL6G.js.map → ConnectedMailInviteCard-2TXUPVV7.js.map} +1 -1
- package/dist/{ConnectedMailInviteCard-OBDYWUFM.cjs → ConnectedMailInviteCard-RSNELYZX.cjs} +5 -5
- package/dist/{ConnectedMailInviteCard-OBDYWUFM.cjs.map → ConnectedMailInviteCard-RSNELYZX.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-2RIERXLW.js → ConnectedNativeDocxComparison-P6GG3ODF.js} +18 -18
- package/dist/ConnectedNativeDocxComparison-P6GG3ODF.js.map +1 -0
- package/dist/{ConnectedNativeDocxComparison-46C7LYGT.cjs → ConnectedNativeDocxComparison-QHAV3K7N.cjs} +19 -19
- package/dist/ConnectedNativeDocxComparison-QHAV3K7N.cjs.map +1 -0
- package/dist/{ConnectedNativeDocxEditor-6XMB2XT7.cjs → ConnectedNativeDocxEditor-6HQD3MHT.cjs} +19 -19
- package/dist/ConnectedNativeDocxEditor-6HQD3MHT.cjs.map +1 -0
- package/dist/{ConnectedNativeDocxEditor-K6X63CPL.js → ConnectedNativeDocxEditor-CWDRJHXN.js} +17 -17
- package/dist/ConnectedNativeDocxEditor-CWDRJHXN.js.map +1 -0
- package/dist/{ConnectedProductionSetDialog-JXQLGDIH.js → ConnectedProductionSetDialog-2SM3ZNBF.js} +3 -3
- package/dist/{ConnectedProductionSetDialog-JXQLGDIH.js.map → ConnectedProductionSetDialog-2SM3ZNBF.js.map} +1 -1
- package/dist/{ConnectedProductionSetDialog-T3Q32XPJ.cjs → ConnectedProductionSetDialog-XNGMUGB6.cjs} +3 -3
- package/dist/{ConnectedProductionSetDialog-T3Q32XPJ.cjs.map → ConnectedProductionSetDialog-XNGMUGB6.cjs.map} +1 -1
- package/dist/{ConnectedStreamedWordArtifact-6UMLSR3G.js → ConnectedStreamedWordArtifact-4SU4FVZE.js} +18 -18
- package/dist/ConnectedStreamedWordArtifact-4SU4FVZE.js.map +1 -0
- package/dist/{ConnectedStreamedWordArtifact-GFFLCGF7.cjs → ConnectedStreamedWordArtifact-5V7VRTEY.cjs} +19 -19
- package/dist/ConnectedStreamedWordArtifact-5V7VRTEY.cjs.map +1 -0
- package/dist/{DocumentReviewCard-SAKLHM4Y.js → DocumentReviewCard-LP33IGEL.js} +18 -18
- package/dist/{DocumentReviewCard-SAKLHM4Y.js.map → DocumentReviewCard-LP33IGEL.js.map} +1 -1
- package/dist/{DocumentReviewCard-XGYMO5YS.cjs → DocumentReviewCard-QV3CM7YP.cjs} +23 -23
- package/dist/{DocumentReviewCard-XGYMO5YS.cjs.map → DocumentReviewCard-QV3CM7YP.cjs.map} +1 -1
- package/dist/{FilesViewerDialog-HNBRY7RQ.js → FilesViewerDialog-FZYXO3MS.js} +29 -29
- package/dist/{FilesViewerDialog-HNBRY7RQ.js.map → FilesViewerDialog-FZYXO3MS.js.map} +1 -1
- package/dist/{FilesViewerDialog-3C6JUMVS.cjs → FilesViewerDialog-JKNA25Q3.cjs} +31 -31
- package/dist/{FilesViewerDialog-3C6JUMVS.cjs.map → FilesViewerDialog-JKNA25Q3.cjs.map} +1 -1
- package/dist/{WorkspaceTableView-DFN4WGRI.js → WorkspaceTableView-IFXCT6AJ.js} +10 -10
- package/dist/{WorkspaceTableView-DFN4WGRI.js.map → WorkspaceTableView-IFXCT6AJ.js.map} +1 -1
- package/dist/{WorkspaceTableView-UOP3EB2F.cjs → WorkspaceTableView-PZVCHSOP.cjs} +12 -12
- package/dist/{WorkspaceTableView-UOP3EB2F.cjs.map → WorkspaceTableView-PZVCHSOP.cjs.map} +1 -1
- package/dist/agents/index.cjs +353 -353
- package/dist/agents/index.js +14 -14
- package/dist/calendar/index.cjs +116 -116
- package/dist/calendar/index.js +1 -1
- package/dist/calls/index.cjs +154 -154
- package/dist/calls/index.js +13 -13
- package/dist/chat/index.cjs +18 -18
- package/dist/chat/index.js +2 -2
- package/dist/{chunk-B7RAN4DM.js → chunk-26RAAEFP.js} +3 -3
- package/dist/{chunk-B7RAN4DM.js.map → chunk-26RAAEFP.js.map} +1 -1
- package/dist/{chunk-GUGSUCIK.js → chunk-2A5QNDV2.js} +3 -3
- package/dist/{chunk-GUGSUCIK.js.map → chunk-2A5QNDV2.js.map} +1 -1
- package/dist/{chunk-WWMVVAA5.js → chunk-2AEWXS4X.js} +8 -8
- package/dist/{chunk-WWMVVAA5.js.map → chunk-2AEWXS4X.js.map} +1 -1
- package/dist/{chunk-HMS3GRMI.cjs → chunk-2Q7LETQX.cjs} +6 -6
- package/dist/{chunk-HMS3GRMI.cjs.map → chunk-2Q7LETQX.cjs.map} +1 -1
- package/dist/{chunk-OZS7THEB.js → chunk-2RDH5PVJ.js} +3 -3
- package/dist/{chunk-OZS7THEB.js.map → chunk-2RDH5PVJ.js.map} +1 -1
- package/dist/{chunk-6XOHTWDR.cjs → chunk-2XTU5H2U.cjs} +69 -69
- package/dist/{chunk-6XOHTWDR.cjs.map → chunk-2XTU5H2U.cjs.map} +1 -1
- package/dist/{chunk-JIFXHVO4.js → chunk-3BSFHBHY.js} +4 -4
- package/dist/{chunk-JIFXHVO4.js.map → chunk-3BSFHBHY.js.map} +1 -1
- package/dist/{chunk-SK6BAW7L.js → chunk-46IG4KY7.js} +103 -104
- package/dist/chunk-46IG4KY7.js.map +1 -0
- package/dist/{chunk-BLAWERIU.cjs → chunk-4P553YX2.cjs} +36 -36
- package/dist/{chunk-BLAWERIU.cjs.map → chunk-4P553YX2.cjs.map} +1 -1
- package/dist/{chunk-UAF2J7P7.cjs → chunk-5HEMXXHR.cjs} +103 -104
- package/dist/chunk-5HEMXXHR.cjs.map +1 -0
- package/dist/{chunk-A4MBPDLX.cjs → chunk-5S52732U.cjs} +6 -6
- package/dist/{chunk-A4MBPDLX.cjs.map → chunk-5S52732U.cjs.map} +1 -1
- package/dist/{chunk-4RFNQRUD.js → chunk-5SUIQS75.js} +16 -16
- package/dist/{chunk-4RFNQRUD.js.map → chunk-5SUIQS75.js.map} +1 -1
- package/dist/{chunk-Y2FPWPDB.js → chunk-5XB3H2TJ.js} +3 -3
- package/dist/{chunk-Y2FPWPDB.js.map → chunk-5XB3H2TJ.js.map} +1 -1
- package/dist/{chunk-NZQZ2HFU.cjs → chunk-64KZM3RZ.cjs} +3 -3
- package/dist/{chunk-NZQZ2HFU.cjs.map → chunk-64KZM3RZ.cjs.map} +1 -1
- package/dist/{chunk-YIJ4MFYM.js → chunk-6U6IY7DB.js} +3 -3
- package/dist/{chunk-YIJ4MFYM.js.map → chunk-6U6IY7DB.js.map} +1 -1
- package/dist/{chunk-K6UKLIRR.js → chunk-AS3HX7LL.js} +3 -3
- package/dist/{chunk-K6UKLIRR.js.map → chunk-AS3HX7LL.js.map} +1 -1
- package/dist/{chunk-LBRJA4ZJ.cjs → chunk-AZVKR4JO.cjs} +3 -3
- package/dist/{chunk-LBRJA4ZJ.cjs.map → chunk-AZVKR4JO.cjs.map} +1 -1
- package/dist/{chunk-RIBQCTBQ.js → chunk-B2NHC2KC.js} +3 -3
- package/dist/{chunk-RIBQCTBQ.js.map → chunk-B2NHC2KC.js.map} +1 -1
- package/dist/{chunk-IXA534S4.js → chunk-BCYFZIG6.js} +13 -13
- package/dist/{chunk-IXA534S4.js.map → chunk-BCYFZIG6.js.map} +1 -1
- package/dist/{chunk-VJLW3UPL.cjs → chunk-BDTPWXUW.cjs} +7 -7
- package/dist/{chunk-VJLW3UPL.cjs.map → chunk-BDTPWXUW.cjs.map} +1 -1
- package/dist/{chunk-EXZPKMMP.js → chunk-BSTVTI5G.js} +14 -14
- package/dist/{chunk-EXZPKMMP.js.map → chunk-BSTVTI5G.js.map} +1 -1
- package/dist/{chunk-OTODKLR3.cjs → chunk-C5CWKZ5D.cjs} +3 -3
- package/dist/{chunk-OTODKLR3.cjs.map → chunk-C5CWKZ5D.cjs.map} +1 -1
- package/dist/{chunk-LPGBRMYS.js → chunk-CHQMVIHR.js} +36 -36
- package/dist/chunk-CHQMVIHR.js.map +1 -0
- package/dist/{chunk-Z6NX57CU.js → chunk-CPOFZYKH.js} +4 -4
- package/dist/{chunk-Z6NX57CU.js.map → chunk-CPOFZYKH.js.map} +1 -1
- package/dist/{chunk-Q4ORI364.cjs → chunk-DBGN4M4F.cjs} +19 -19
- package/dist/{chunk-Q4ORI364.cjs.map → chunk-DBGN4M4F.cjs.map} +1 -1
- package/dist/{chunk-3TECBO75.cjs → chunk-DCYVHUSU.cjs} +54 -54
- package/dist/{chunk-3TECBO75.cjs.map → chunk-DCYVHUSU.cjs.map} +1 -1
- package/dist/{chunk-PZXEXHKB.cjs → chunk-DIE5ENQC.cjs} +28 -28
- package/dist/{chunk-PZXEXHKB.cjs.map → chunk-DIE5ENQC.cjs.map} +1 -1
- package/dist/{chunk-TVLY7FTU.js → chunk-DW7LSBIW.js} +3 -3
- package/dist/{chunk-TVLY7FTU.js.map → chunk-DW7LSBIW.js.map} +1 -1
- package/dist/{chunk-RCOJ7JG5.cjs → chunk-EBNY3RTL.cjs} +4 -4
- package/dist/{chunk-RCOJ7JG5.cjs.map → chunk-EBNY3RTL.cjs.map} +1 -1
- package/dist/{chunk-FEBLYTME.js → chunk-ER36PSS7.js} +5 -5
- package/dist/{chunk-FEBLYTME.js.map → chunk-ER36PSS7.js.map} +1 -1
- package/dist/{chunk-VIRQYEFL.cjs → chunk-F5T4W2R2.cjs} +140 -140
- package/dist/chunk-F5T4W2R2.cjs.map +1 -0
- package/dist/{chunk-RQNNHO44.cjs → chunk-GE2O6S44.cjs} +4 -4
- package/dist/{chunk-RQNNHO44.cjs.map → chunk-GE2O6S44.cjs.map} +1 -1
- package/dist/{chunk-4UMSQ67B.js → chunk-H57PBOFE.js} +3 -3
- package/dist/{chunk-4UMSQ67B.js.map → chunk-H57PBOFE.js.map} +1 -1
- package/dist/{chunk-7OPOPYV6.cjs → chunk-H5OLHP2U.cjs} +3 -3
- package/dist/{chunk-7OPOPYV6.cjs.map → chunk-H5OLHP2U.cjs.map} +1 -1
- package/dist/{chunk-VK5Q5JXU.cjs → chunk-HDPT7D6F.cjs} +3 -3
- package/dist/{chunk-VK5Q5JXU.cjs.map → chunk-HDPT7D6F.cjs.map} +1 -1
- package/dist/{chunk-HU7MB33Q.js → chunk-HLVLPDDD.js} +3 -3
- package/dist/{chunk-HU7MB33Q.js.map → chunk-HLVLPDDD.js.map} +1 -1
- package/dist/{chunk-CLPDKHSP.cjs → chunk-HYDIQEDT.cjs} +12 -12
- package/dist/{chunk-CLPDKHSP.cjs.map → chunk-HYDIQEDT.cjs.map} +1 -1
- package/dist/{chunk-HUE76NAI.cjs → chunk-I6SPGHFY.cjs} +2 -2
- package/dist/{chunk-HUE76NAI.cjs.map → chunk-I6SPGHFY.cjs.map} +1 -1
- package/dist/{chunk-M6XUGXCY.cjs → chunk-IHJ7BEI5.cjs} +741 -741
- package/dist/chunk-IHJ7BEI5.cjs.map +1 -0
- package/dist/{chunk-WLQAD6ZY.js → chunk-IL6OWGAU.js} +744 -744
- package/dist/chunk-IL6OWGAU.js.map +1 -0
- package/dist/{chunk-KXRGVY3M.cjs → chunk-ILLWGL7Q.cjs} +4 -4
- package/dist/{chunk-KXRGVY3M.cjs.map → chunk-ILLWGL7Q.cjs.map} +1 -1
- package/dist/{chunk-WFNEZT7S.cjs → chunk-IOCEKN44.cjs} +4 -4
- package/dist/{chunk-WFNEZT7S.cjs.map → chunk-IOCEKN44.cjs.map} +1 -1
- package/dist/{chunk-MFEJKCCZ.js → chunk-JGA2JJEL.js} +3 -3
- package/dist/{chunk-MFEJKCCZ.js.map → chunk-JGA2JJEL.js.map} +1 -1
- package/dist/{chunk-UCQ3VXRB.js → chunk-JM7Z3QNS.js} +5 -5
- package/dist/{chunk-UCQ3VXRB.js.map → chunk-JM7Z3QNS.js.map} +1 -1
- package/dist/{chunk-3KNKAZ5D.cjs → chunk-K3C4WECV.cjs} +5 -5
- package/dist/{chunk-3KNKAZ5D.cjs.map → chunk-K3C4WECV.cjs.map} +1 -1
- package/dist/{chunk-DGG35TPO.cjs → chunk-KB2FH26M.cjs} +4 -4
- package/dist/{chunk-DGG35TPO.cjs.map → chunk-KB2FH26M.cjs.map} +1 -1
- package/dist/{chunk-MB3IQLNN.cjs → chunk-L4USMBHU.cjs} +18 -18
- package/dist/chunk-L4USMBHU.cjs.map +1 -0
- package/dist/{chunk-XIEX3HO3.js → chunk-L4YGZJYR.js} +3 -3
- package/dist/{chunk-XIEX3HO3.js.map → chunk-L4YGZJYR.js.map} +1 -1
- package/dist/{chunk-KNC77LZZ.cjs → chunk-LMOLE5PS.cjs} +3 -3
- package/dist/{chunk-KNC77LZZ.cjs.map → chunk-LMOLE5PS.cjs.map} +1 -1
- package/dist/{chunk-PYLG3M6G.js → chunk-LTRFQ2IC.js} +2 -2
- package/dist/{chunk-PYLG3M6G.js.map → chunk-LTRFQ2IC.js.map} +1 -1
- package/dist/{chunk-636KUL53.js → chunk-NSJUMOLN.js} +5 -5
- package/dist/{chunk-636KUL53.js.map → chunk-NSJUMOLN.js.map} +1 -1
- package/dist/{chunk-7SJXYEZI.cjs → chunk-OAIOOVFN.cjs} +36 -36
- package/dist/chunk-OAIOOVFN.cjs.map +1 -0
- package/dist/{chunk-FKPFKSDT.js → chunk-PA2I7GLY.js} +6 -6
- package/dist/{chunk-FKPFKSDT.js.map → chunk-PA2I7GLY.js.map} +1 -1
- package/dist/{chunk-4KARJ4CC.js → chunk-PCAWLVHE.js} +3 -3
- package/dist/{chunk-4KARJ4CC.js.map → chunk-PCAWLVHE.js.map} +1 -1
- package/dist/{chunk-7QDLONHA.js → chunk-PPFTNP6J.js} +11 -11
- package/dist/chunk-PPFTNP6J.js.map +1 -0
- package/dist/{chunk-2FPBFLOX.cjs → chunk-Q4X5RK4A.cjs} +9 -3
- package/dist/chunk-Q4X5RK4A.cjs.map +1 -0
- package/dist/{chunk-4VUKYB32.cjs → chunk-Q5TOUT2C.cjs} +4 -4
- package/dist/{chunk-4VUKYB32.cjs.map → chunk-Q5TOUT2C.cjs.map} +1 -1
- package/dist/{chunk-DU3H4WC6.cjs → chunk-QIEUKIBH.cjs} +4 -4
- package/dist/{chunk-DU3H4WC6.cjs.map → chunk-QIEUKIBH.cjs.map} +1 -1
- package/dist/{chunk-5YBH5CQD.cjs → chunk-QJNHVQUQ.cjs} +26 -26
- package/dist/{chunk-5YBH5CQD.cjs.map → chunk-QJNHVQUQ.cjs.map} +1 -1
- package/dist/{chunk-C33VIPE2.js → chunk-QZ6XGYGW.js} +9 -3
- package/dist/chunk-QZ6XGYGW.js.map +1 -0
- package/dist/{chunk-YRVE6RX5.cjs → chunk-RB6MAAS7.cjs} +4 -4
- package/dist/{chunk-YRVE6RX5.cjs.map → chunk-RB6MAAS7.cjs.map} +1 -1
- package/dist/{chunk-KPD7WAXP.js → chunk-S6QBLVPP.js} +3 -3
- package/dist/{chunk-KPD7WAXP.js.map → chunk-S6QBLVPP.js.map} +1 -1
- package/dist/{chunk-TIQZ7CXZ.js → chunk-SOLSDXOZ.js} +83 -83
- package/dist/chunk-SOLSDXOZ.js.map +1 -0
- package/dist/{chunk-ZZE3ORJS.js → chunk-SOZIHPO2.js} +3 -3
- package/dist/{chunk-ZZE3ORJS.js.map → chunk-SOZIHPO2.js.map} +1 -1
- package/dist/{chunk-TSP5JJ56.js → chunk-VUXWBUZ7.js} +11 -11
- package/dist/{chunk-TSP5JJ56.js.map → chunk-VUXWBUZ7.js.map} +1 -1
- package/dist/{chunk-NZ26UYEQ.cjs → chunk-VWX36C4Y.cjs} +67 -67
- package/dist/{chunk-NZ26UYEQ.cjs.map → chunk-VWX36C4Y.cjs.map} +1 -1
- package/dist/{chunk-YACOI5ZU.cjs → chunk-WA2U4G43.cjs} +62 -62
- package/dist/{chunk-YACOI5ZU.cjs.map → chunk-WA2U4G43.cjs.map} +1 -1
- package/dist/{chunk-PSJAFPMH.js → chunk-WLWZAS7J.js} +4 -4
- package/dist/{chunk-PSJAFPMH.js.map → chunk-WLWZAS7J.js.map} +1 -1
- package/dist/{chunk-GNKQVCMW.cjs → chunk-WVEYUH6C.cjs} +6 -6
- package/dist/{chunk-GNKQVCMW.cjs.map → chunk-WVEYUH6C.cjs.map} +1 -1
- package/dist/{chunk-2F65OOU3.js → chunk-YB2P5Y52.js} +7 -7
- package/dist/{chunk-2F65OOU3.js.map → chunk-YB2P5Y52.js.map} +1 -1
- package/dist/collaboration/index.cjs +1 -1
- package/dist/collaboration/index.js +1 -1
- package/dist/connect/docx.cjs +22 -22
- package/dist/connect/docx.js +18 -18
- package/dist/connect/index.cjs +1176 -1176
- package/dist/connect/index.js +87 -87
- package/dist/connect/viewer.cjs +28 -28
- package/dist/connect/viewer.js +27 -27
- package/dist/dashboards/index.cjs +1 -1
- package/dist/dashboards/index.js +1 -1
- package/dist/embed/index.cjs +42 -42
- package/dist/embed/index.js +36 -36
- package/dist/facts/index.cjs +44 -44
- package/dist/facts/index.js +3 -3
- package/dist/files/index.cjs +226 -226
- package/dist/files/index.js +5 -5
- package/dist/index.cjs +1631 -1631
- package/dist/index.js +47 -47
- package/dist/settings/index.cjs +153 -153
- package/dist/settings/index.js +4 -4
- package/dist/shell/Sidebar.d.ts +4 -2
- package/dist/shell/index.cjs +89 -89
- package/dist/shell/index.js +10 -10
- package/dist/shell/use-sidebar-controller.d.ts +3 -3
- package/dist/studio/index.cjs +18 -18
- package/dist/studio/index.js +15 -15
- package/dist/workflow-canvas/index.cjs +66 -66
- package/dist/workflow-canvas/index.js +42 -42
- package/dist/workspaces/index.cjs +20 -20
- package/dist/workspaces/index.js +3 -3
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +5 -5
- package/dist/ConnectedNativeDocxComparison-2RIERXLW.js.map +0 -1
- package/dist/ConnectedNativeDocxComparison-46C7LYGT.cjs.map +0 -1
- package/dist/ConnectedNativeDocxEditor-6XMB2XT7.cjs.map +0 -1
- package/dist/ConnectedNativeDocxEditor-K6X63CPL.js.map +0 -1
- package/dist/ConnectedStreamedWordArtifact-6UMLSR3G.js.map +0 -1
- package/dist/ConnectedStreamedWordArtifact-GFFLCGF7.cjs.map +0 -1
- package/dist/chunk-2FPBFLOX.cjs.map +0 -1
- package/dist/chunk-7QDLONHA.js.map +0 -1
- package/dist/chunk-7SJXYEZI.cjs.map +0 -1
- package/dist/chunk-C33VIPE2.js.map +0 -1
- package/dist/chunk-LPGBRMYS.js.map +0 -1
- package/dist/chunk-M6XUGXCY.cjs.map +0 -1
- package/dist/chunk-MB3IQLNN.cjs.map +0 -1
- package/dist/chunk-SK6BAW7L.js.map +0 -1
- package/dist/chunk-TIQZ7CXZ.js.map +0 -1
- package/dist/chunk-UAF2J7P7.cjs.map +0 -1
- package/dist/chunk-VIRQYEFL.cjs.map +0 -1
- package/dist/chunk-WLQAD6ZY.js.map +0 -1
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
4
|
+
var chunkOAIOOVFN_cjs = require('./chunk-OAIOOVFN.cjs');
|
|
5
|
+
var chunkIOCEKN44_cjs = require('./chunk-IOCEKN44.cjs');
|
|
6
|
+
var chunkF5T4W2R2_cjs = require('./chunk-F5T4W2R2.cjs');
|
|
7
|
+
var chunk5HEMXXHR_cjs = require('./chunk-5HEMXXHR.cjs');
|
|
8
8
|
var chunkBFKTZUFT_cjs = require('./chunk-BFKTZUFT.cjs');
|
|
9
9
|
var chunkWV65MJ43_cjs = require('./chunk-WV65MJ43.cjs');
|
|
10
|
+
var chunkZBP4ZSAJ_cjs = require('./chunk-ZBP4ZSAJ.cjs');
|
|
11
|
+
var chunkMOIZ2R5X_cjs = require('./chunk-MOIZ2R5X.cjs');
|
|
10
12
|
var chunkZW6FPIFC_cjs = require('./chunk-ZW6FPIFC.cjs');
|
|
11
13
|
var chunkZT5MIFLC_cjs = require('./chunk-ZT5MIFLC.cjs');
|
|
12
|
-
var chunkZBP4ZSAJ_cjs = require('./chunk-ZBP4ZSAJ.cjs');
|
|
13
14
|
var chunkUIXY4HKM_cjs = require('./chunk-UIXY4HKM.cjs');
|
|
14
|
-
var chunkMOIZ2R5X_cjs = require('./chunk-MOIZ2R5X.cjs');
|
|
15
15
|
var react = require('@arbidocs/react');
|
|
16
16
|
var react$1 = require('react');
|
|
17
17
|
var lucideReact = require('lucide-react');
|
|
@@ -19,553 +19,207 @@ var ui = require('@arbidocs/react/ui');
|
|
|
19
19
|
var jsxRuntime = require('react/jsx-runtime');
|
|
20
20
|
var browser = require('@arbidocs/sdk/browser');
|
|
21
21
|
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
function StartCallButton(props) {
|
|
23
|
+
const enabled = react.useCallsEnabled();
|
|
24
|
+
const canHost = react.useCanHostCalls();
|
|
25
|
+
return enabled && (canHost || props.isLive) ? /* @__PURE__ */ jsxRuntime.jsx(EnabledStartCallButton, { ...props }) : null;
|
|
26
|
+
}
|
|
27
|
+
function EnabledStartCallButton({
|
|
28
|
+
onStart,
|
|
29
|
+
isLive = false,
|
|
30
|
+
label = "Start call",
|
|
31
|
+
testId = "start-call-button"
|
|
28
32
|
}) {
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
33
|
+
const [isStarting, setIsStarting] = react$1.useState(false);
|
|
34
|
+
const inCall = react.useCallSession((s) => s.active !== null);
|
|
35
|
+
const text = inCall ? "Already in a call" : isLive ? "Join call" : label;
|
|
36
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Tooltip, { children: [
|
|
37
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
38
|
+
ui.Button,
|
|
39
|
+
{
|
|
40
|
+
type: "button",
|
|
41
|
+
variant: "ghost",
|
|
42
|
+
size: "icon",
|
|
43
|
+
"aria-label": isLive ? "Join call" : label,
|
|
44
|
+
"data-testid": testId,
|
|
45
|
+
"data-live": isLive || void 0,
|
|
46
|
+
disabled: isStarting || inCall,
|
|
47
|
+
onClick: () => {
|
|
48
|
+
setIsStarting(true);
|
|
49
|
+
void onStart().finally(() => setIsStarting(false));
|
|
50
|
+
},
|
|
51
|
+
className: ui.cn(
|
|
52
|
+
"text-muted-foreground hover:text-foreground",
|
|
53
|
+
isLive && "text-green-text hover:text-green-text"
|
|
54
|
+
),
|
|
55
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Phone, { className: ui.cn("size-5", isLive && "animate-pulse") })
|
|
56
|
+
}
|
|
57
|
+
) }),
|
|
58
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.TooltipContent, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: text }) })
|
|
59
|
+
] });
|
|
60
|
+
}
|
|
61
|
+
var INVITE_LINK_HINT = "will get an invitation to create an ARBI account and join";
|
|
62
|
+
var NO_KEY_REASON = "Cannot receive encrypted calls yet";
|
|
63
|
+
var NO_EMAIL_REASON = "No e-mail address to send a link to";
|
|
64
|
+
function contactName(contact) {
|
|
65
|
+
return contact.card?.name?.trim() || [contact.card?.given_name, contact.card?.family_name].filter(Boolean).join(" ") || (contact.user ? ui.getUserDisplayName(contact.user) : "") || contactEmail(contact) || "Contact";
|
|
66
|
+
}
|
|
67
|
+
function contactEmail(contact) {
|
|
68
|
+
return contact.email ?? contact.user?.email ?? contact.card?.emails?.[0]?.email ?? null;
|
|
69
|
+
}
|
|
70
|
+
function callContactOf(contact) {
|
|
71
|
+
if (!contact.external_id || contact.status === "failed") return null;
|
|
72
|
+
if (contact.user && ui.isAgent(contact.user)) return null;
|
|
73
|
+
return {
|
|
74
|
+
contactExtId: contact.external_id,
|
|
75
|
+
user: contact.user ?? null,
|
|
76
|
+
name: contactName(contact),
|
|
77
|
+
email: contactEmail(contact)
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function userCandidate(user, section, status, contactExtId = null) {
|
|
81
|
+
const ringable = status !== "ring" || !!user.encryption_public_key;
|
|
82
|
+
return {
|
|
83
|
+
id: user.external_id,
|
|
84
|
+
name: ui.getUserDisplayName(user) || user.email,
|
|
85
|
+
email: user.email ?? null,
|
|
86
|
+
section,
|
|
87
|
+
status: ringable ? status : "unavailable",
|
|
88
|
+
reason: ringable ? void 0 : NO_KEY_REASON,
|
|
89
|
+
user,
|
|
90
|
+
contactExtId
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function buildCallCandidates(opts) {
|
|
94
|
+
const seen = /* @__PURE__ */ new Set();
|
|
95
|
+
const out = [];
|
|
96
|
+
const add = (c) => {
|
|
97
|
+
if (seen.has(c.id)) return;
|
|
98
|
+
seen.add(c.id);
|
|
99
|
+
out.push(c);
|
|
100
|
+
};
|
|
101
|
+
const people = (users) => users.filter((u) => !ui.isAgent(u) && u.external_id !== opts.me);
|
|
102
|
+
if (opts.scope !== "contacts") {
|
|
103
|
+
for (const u of people(opts.members)) add(userCandidate(u, "members", "ring"));
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
const contacts = (opts.contacts ?? []).filter((c) => !(c.user && ui.isAgent(c.user)));
|
|
107
|
+
const contactOf = new Map(
|
|
108
|
+
contacts.filter((c) => c.user).map((c) => [c.user.external_id, c.contactExtId])
|
|
109
|
+
);
|
|
110
|
+
for (const u of people(opts.members)) {
|
|
111
|
+
const contactId = contactOf.get(u.external_id) ?? opts.contactIdOf?.(u) ?? null;
|
|
112
|
+
add(userCandidate(u, "members", contactId ? "ring" : "add-contact", contactId));
|
|
113
|
+
}
|
|
114
|
+
for (const c of contacts) {
|
|
115
|
+
if (c.user) {
|
|
116
|
+
if (c.user.external_id === opts.me) continue;
|
|
117
|
+
add(userCandidate(c.user, "contacts", "ring", c.contactExtId));
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const status = c.email ? "invite" : "unavailable";
|
|
121
|
+
add({
|
|
122
|
+
id: c.contactExtId,
|
|
123
|
+
name: c.name,
|
|
124
|
+
email: c.email,
|
|
125
|
+
section: "contacts",
|
|
126
|
+
status,
|
|
127
|
+
reason: c.email ? INVITE_LINK_HINT : NO_EMAIL_REASON,
|
|
128
|
+
user: null,
|
|
129
|
+
contactExtId: c.contactExtId
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
function isPickable(c) {
|
|
135
|
+
return c.status === "ring" || c.status === "invite";
|
|
136
|
+
}
|
|
137
|
+
function matchesQuery(c, query) {
|
|
138
|
+
const q = query.trim().toLowerCase();
|
|
139
|
+
if (!q) return true;
|
|
140
|
+
return c.name.toLowerCase().includes(q) || (c.email ?? "").toLowerCase().includes(q);
|
|
141
|
+
}
|
|
142
|
+
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
143
|
+
var COPY = {
|
|
144
|
+
workspace: {
|
|
145
|
+
title: "Call thread members",
|
|
146
|
+
description: "Only members of this thread\u2019s workspace can join. Pick who to ring \u2014 or nobody, and share the call from the thread.",
|
|
147
|
+
action: "Start call"
|
|
148
|
+
},
|
|
149
|
+
chat: {
|
|
150
|
+
title: "Call the group",
|
|
151
|
+
description: "The people you pick are rung.",
|
|
152
|
+
action: "Start call"
|
|
153
|
+
},
|
|
154
|
+
contacts: {
|
|
155
|
+
title: "New call",
|
|
156
|
+
description: "Your contacts with an ARBI account are rung. Others get an invitation to create an account and join.",
|
|
157
|
+
action: "Start call"
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
function CandidateRow({
|
|
161
|
+
candidate,
|
|
162
|
+
checked,
|
|
163
|
+
onToggle,
|
|
164
|
+
onAddContact,
|
|
165
|
+
adding
|
|
166
|
+
}) {
|
|
167
|
+
const pickable = isPickable(candidate);
|
|
168
|
+
const hint = candidate.status === "invite" ? candidate.reason : candidate.status === "add-contact" ? "Not in your contacts" : void 0;
|
|
169
|
+
const row = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
170
|
+
"li",
|
|
49
171
|
{
|
|
50
|
-
className:
|
|
51
|
-
|
|
52
|
-
|
|
172
|
+
className: ui.cn(
|
|
173
|
+
"flex items-center gap-3 rounded-md px-2 py-1.5",
|
|
174
|
+
pickable ? "hover:bg-muted" : "opacity-60"
|
|
175
|
+
),
|
|
176
|
+
"data-testid": `call-picker-row-${candidate.id}`,
|
|
177
|
+
"data-status": candidate.status,
|
|
178
|
+
"aria-disabled": !pickable || void 0,
|
|
53
179
|
children: [
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
180
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
181
|
+
ui.Checkbox,
|
|
182
|
+
{
|
|
183
|
+
checked,
|
|
184
|
+
disabled: !pickable,
|
|
185
|
+
onCheckedChange: onToggle,
|
|
186
|
+
"aria-label": `Invite ${candidate.name}`,
|
|
187
|
+
"data-testid": `call-picker-check-${candidate.id}`
|
|
188
|
+
}
|
|
189
|
+
),
|
|
190
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
191
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate text-sm", children: candidate.name }),
|
|
192
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "block truncate text-xs text-muted-foreground", children: [
|
|
193
|
+
candidate.email,
|
|
194
|
+
hint && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-1 inline-flex items-center gap-1", children: [
|
|
195
|
+
candidate.status === "invite" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Mail, { className: "size-3", "aria-hidden": true }),
|
|
196
|
+
candidate.email ? `\xB7 ${hint}` : hint
|
|
197
|
+
] })
|
|
198
|
+
] })
|
|
199
|
+
] }),
|
|
200
|
+
candidate.status === "add-contact" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58
201
|
ui.Button,
|
|
59
202
|
{
|
|
60
203
|
type: "button",
|
|
61
204
|
size: "sm",
|
|
62
|
-
|
|
63
|
-
disabled:
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
children: inThisCall ? "In call" : "Join"
|
|
205
|
+
variant: "outline",
|
|
206
|
+
disabled: adding,
|
|
207
|
+
onClick: onAddContact,
|
|
208
|
+
"data-testid": `call-picker-add-${candidate.id}`,
|
|
209
|
+
children: [
|
|
210
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserPlus, { className: "mr-1 size-3.5" }),
|
|
211
|
+
"Add contact"
|
|
212
|
+
]
|
|
71
213
|
}
|
|
72
214
|
)
|
|
73
215
|
]
|
|
74
216
|
}
|
|
75
217
|
);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const profile = me ? arbi.user.profile() : null;
|
|
82
|
-
return react$1.useMemo(() => {
|
|
83
|
-
if (profile)
|
|
84
|
-
return ui.getUserDisplayName({ given_name: profile.givenName, family_name: profile.familyName });
|
|
85
|
-
const user = byId(identity);
|
|
86
|
-
if (user) return ui.getUserDisplayName(user);
|
|
87
|
-
return (fallbackName || identity).trim().split(/\s+/).join(" ");
|
|
88
|
-
}, [profile, byId, identity, fallbackName]);
|
|
89
|
-
}
|
|
90
|
-
function CallConversationEmpty({ callExtId }) {
|
|
91
|
-
const { inCall, transcribing } = chunk7SJXYEZI_cjs.useMyCallStatus(callExtId);
|
|
92
|
-
const live = react.useCallSession((s) => !!s.liveCalls[callExtId]) || inCall;
|
|
93
|
-
if (!live) {
|
|
94
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
95
|
-
chunkZW6FPIFC_cjs.EmptyState,
|
|
96
|
-
{
|
|
97
|
-
icon: lucideReact.AudioLines,
|
|
98
|
-
title: "No transcript",
|
|
99
|
-
description: "This call was not transcribed. When a call here is transcribed, what people say appears in this conversation.",
|
|
100
|
-
className: "mx-auto my-8 max-w-xl",
|
|
101
|
-
testId: "call-conversation-empty"
|
|
102
|
-
}
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
106
|
-
chunkZW6FPIFC_cjs.EmptyState,
|
|
107
|
-
{
|
|
108
|
-
icon: transcribing ? lucideReact.Captions : lucideReact.CaptionsOff,
|
|
109
|
-
title: "Call in progress \u2014 the transcript will appear here",
|
|
110
|
-
description: transcribing ? "Transcription is on: what people say shows up here as they speak." : "Transcription is off. The host can turn it on with CC in the call.",
|
|
111
|
-
className: "mx-auto my-8 max-w-xl",
|
|
112
|
-
testId: "call-conversation-empty"
|
|
113
|
-
}
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
function ProvisionalRow({ identity }) {
|
|
117
|
-
const name = useCallPersonName(identity);
|
|
118
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
119
|
-
chunkZBP4ZSAJ_cjs.ProvisionalTranscriptLine,
|
|
120
|
-
{
|
|
121
|
-
speakerId: identity,
|
|
122
|
-
speakerName: name,
|
|
123
|
-
speaker: /* @__PURE__ */ jsxRuntime.jsx(chunkUAF2J7P7_cjs.CallUserPill, { identity })
|
|
124
|
-
}
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
function ProvisionalSpeakers({ ids }) {
|
|
128
|
-
if (!ids.length) return null;
|
|
129
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pb-2", "data-testid": "transcript-provisional-rows", children: ids.map((id) => /* @__PURE__ */ jsxRuntime.jsx(ProvisionalRow, { identity: id }, id)) });
|
|
130
|
-
}
|
|
131
|
-
var LINE_WAIT_MS = 1e4;
|
|
132
|
-
var MIN_SPEECH_MS = 800;
|
|
133
|
-
function useProvisionalSpeakers(callExtId, lines) {
|
|
134
|
-
const { inCall, transcribing } = chunk7SJXYEZI_cjs.useMyCallStatus(callExtId);
|
|
135
|
-
const speaking = chunk7SJXYEZI_cjs.useSpeakingIds();
|
|
136
|
-
const pending = react$1.useRef(/* @__PURE__ */ new Map());
|
|
137
|
-
const [, tick] = react$1.useState(0);
|
|
138
|
-
const active = inCall && transcribing;
|
|
139
|
-
const now = Date.now();
|
|
140
|
-
if (active) {
|
|
141
|
-
for (const id of speaking) {
|
|
142
|
-
const p = pending.current.get(id);
|
|
143
|
-
if (p) p.lastHeardAt = now;
|
|
144
|
-
else pending.current.set(id, { startedAt: now, lastHeardAt: now });
|
|
145
|
-
}
|
|
146
|
-
} else if (pending.current.size) {
|
|
147
|
-
pending.current.clear();
|
|
148
|
-
}
|
|
149
|
-
const latest = react$1.useMemo(() => {
|
|
150
|
-
const m = /* @__PURE__ */ new Map();
|
|
151
|
-
for (const l of lines) m.set(l.speakerId, Math.max(m.get(l.speakerId) ?? 0, l.at));
|
|
152
|
-
return m;
|
|
153
|
-
}, [lines]);
|
|
154
|
-
for (const [id, p] of [...pending.current]) {
|
|
155
|
-
const arrived = (latest.get(id) ?? 0) >= p.startedAt - 3e3;
|
|
156
|
-
const stale = !speaking.includes(id) && now - p.lastHeardAt > LINE_WAIT_MS;
|
|
157
|
-
if (arrived && !speaking.includes(id) || stale) pending.current.delete(id);
|
|
158
|
-
else if (arrived) p.startedAt = now;
|
|
159
|
-
}
|
|
160
|
-
const waiting = pending.current.size > 0;
|
|
161
|
-
react$1.useEffect(() => {
|
|
162
|
-
if (!waiting) return;
|
|
163
|
-
const id = setInterval(() => tick((n) => n + 1), 1e3);
|
|
164
|
-
return () => clearInterval(id);
|
|
165
|
-
}, [waiting]);
|
|
166
|
-
return [...pending.current].filter(([, p]) => p.lastHeardAt - p.startedAt >= MIN_SPEECH_MS).map(([id]) => id);
|
|
167
|
-
}
|
|
168
|
-
var { isTranscriptMessage, parseTranscriptContent } = browser.chats;
|
|
169
|
-
function ConnectedCallChatHistory({
|
|
170
|
-
chat,
|
|
171
|
-
messages,
|
|
172
|
-
items,
|
|
173
|
-
renderItem,
|
|
174
|
-
loadOlder,
|
|
175
|
-
memberById,
|
|
176
|
-
senderName,
|
|
177
|
-
myExtId,
|
|
178
|
-
formatTime,
|
|
179
|
-
formatDay
|
|
180
|
-
}) {
|
|
181
|
-
const arbi = react.useArbi();
|
|
182
|
-
const [view, setView] = react$1.useState("all");
|
|
183
|
-
react$1.useEffect(() => setView("all"), [chat?.external_id]);
|
|
184
|
-
const recordingsCallExtId = chat?.call_ext_id ?? null;
|
|
185
|
-
const pendingRecording = chunkZT5MIFLC_cjs.usePendingRecording();
|
|
186
|
-
react$1.useEffect(() => {
|
|
187
|
-
if (pendingRecording && recordingsCallExtId) setView("recordings");
|
|
188
|
-
}, [pendingRecording, recordingsCallExtId]);
|
|
189
|
-
const latestCallCards = react$1.useMemo(() => {
|
|
190
|
-
const latest = /* @__PURE__ */ new Map();
|
|
191
|
-
for (const m of messages)
|
|
192
|
-
if (m.kind === "call" && m.call_ext_id && !m.deleted) latest.set(m.call_ext_id, m.external_id);
|
|
193
|
-
return new Set(latest.values());
|
|
194
|
-
}, [messages]);
|
|
195
|
-
const hasRecTranscript = react$1.useMemo(
|
|
196
|
-
() => react.hasRecordingTranscript(messages, react.chatTranscriptRef),
|
|
197
|
-
[messages]
|
|
198
|
-
);
|
|
199
|
-
const recordingWindows = react.useRecordingWindows(recordingsCallExtId, hasRecTranscript);
|
|
200
|
-
const supersededTranscript = react$1.useMemo(
|
|
201
|
-
() => react.supersededTranscriptLines(messages, react.chatTranscriptRef, recordingWindows),
|
|
202
|
-
[messages, recordingWindows]
|
|
203
|
-
);
|
|
204
|
-
const transcriptMessages = react$1.useMemo(
|
|
205
|
-
() => react.sortTranscriptMessages(
|
|
206
|
-
messages.filter((m) => isTranscriptMessage(m) && !m.deleted && !supersededTranscript.has(m))
|
|
207
|
-
),
|
|
208
|
-
[messages, supersededTranscript]
|
|
209
|
-
);
|
|
210
|
-
const hasTranscript = transcriptMessages.length > 0;
|
|
211
|
-
const { data: meetingCall } = react.useCall(hasTranscript ? chat?.call_ext_id : null);
|
|
212
|
-
const isHost = !!meetingCall?.is_creator;
|
|
213
|
-
const [meetingTitle, setMeetingTitle] = react$1.useState(null);
|
|
214
|
-
react$1.useEffect(() => {
|
|
215
|
-
if (!chat || !isHost && !recordingsCallExtId) return;
|
|
216
|
-
let cancelled = false;
|
|
217
|
-
arbi.chats.title(chat).then((t) => !cancelled && setMeetingTitle(t)).catch(() => void 0);
|
|
218
|
-
return () => {
|
|
219
|
-
cancelled = true;
|
|
220
|
-
};
|
|
221
|
-
}, [arbi, isHost, chat, recordingsCallExtId]);
|
|
222
|
-
const transcriptSpeaker = (msg) => {
|
|
223
|
-
const parsed = msg.decryptFailed ? null : parseTranscriptContent(msg.content);
|
|
224
|
-
return { parsed, speakerId: parsed?.speaker_identity || msg.sender_ext_id || "" };
|
|
225
|
-
};
|
|
226
|
-
const transcriptExport = react$1.useMemo(
|
|
227
|
-
() => transcriptMessages.filter((m) => !m.decryptFailed).map((m) => {
|
|
228
|
-
const parsed = parseTranscriptContent(m.content);
|
|
229
|
-
const speakerId = parsed?.speaker_identity || m.sender_ext_id || "";
|
|
230
|
-
return {
|
|
231
|
-
speaker: parsed?.speaker_name || (memberById(speakerId) ? senderName(speakerId) : "") || "Former member",
|
|
232
|
-
at: parsed?.started_at ?? m.created_at,
|
|
233
|
-
text: parsed?.text ?? m.content ?? ""
|
|
234
|
-
};
|
|
235
|
-
}),
|
|
236
|
-
[transcriptMessages, memberById, senderName]
|
|
237
|
-
);
|
|
238
|
-
const transcriptLayout = react$1.useMemo(() => {
|
|
239
|
-
const shown = view === "transcript" ? transcriptMessages : messages;
|
|
240
|
-
const continued = chunkZBP4ZSAJ_cjs.transcriptRuns(
|
|
241
|
-
shown,
|
|
242
|
-
(m) => isTranscriptMessage(m) && !supersededTranscript.has(m) ? transcriptSpeaker(m).speakerId : null,
|
|
243
|
-
(m) => Date.parse(transcriptSpeaker(m).parsed?.started_at ?? m.created_at ?? "") || 0
|
|
244
|
-
);
|
|
245
|
-
return { continued };
|
|
246
|
-
}, [view, messages, transcriptMessages, supersededTranscript]);
|
|
247
|
-
const transcriptEntry = (msg) => {
|
|
248
|
-
const { parsed, speakerId } = transcriptSpeaker(msg);
|
|
249
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
250
|
-
chunkWFNEZT7S_cjs.TranscriptEntry,
|
|
251
|
-
{
|
|
252
|
-
speakerId,
|
|
253
|
-
speakerName: speakerId === myExtId ? "Me" : parsed?.speaker_name || (memberById(speakerId) ? senderName(speakerId) : senderName(msg.sender_ext_id)),
|
|
254
|
-
text: parsed?.text ?? msg.content ?? "",
|
|
255
|
-
at: parsed?.started_at ?? msg.created_at,
|
|
256
|
-
continued: transcriptLayout.continued.has(msg)
|
|
257
|
-
},
|
|
258
|
-
msg.external_id
|
|
259
|
-
);
|
|
260
|
-
};
|
|
261
|
-
const chatLines = react$1.useMemo(
|
|
262
|
-
() => transcriptMessages.map((m) => {
|
|
263
|
-
const { parsed, speakerId } = transcriptSpeaker(m);
|
|
264
|
-
return { speakerId, at: Date.parse(parsed?.started_at ?? m.created_at ?? "") || 0 };
|
|
265
|
-
}),
|
|
266
|
-
[transcriptMessages]
|
|
267
|
-
);
|
|
268
|
-
const provisionalSpeakers = useProvisionalSpeakers(recordingsCallExtId, chatLines);
|
|
269
|
-
const filterOptions = [
|
|
270
|
-
{ value: "all", label: "All" },
|
|
271
|
-
{ value: "chat", label: "Chat", testId: "chat-filter" },
|
|
272
|
-
{
|
|
273
|
-
value: "transcript",
|
|
274
|
-
label: "Transcript",
|
|
275
|
-
count: transcriptMessages.length,
|
|
276
|
-
testId: "transcript-filter"
|
|
277
|
-
},
|
|
278
|
-
...recordingsCallExtId ? [{ value: "recordings", label: "Recordings", testId: "recordings-filter" }] : []
|
|
279
|
-
];
|
|
280
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
281
|
-
messages.length === 0 && recordingsCallExtId && /* @__PURE__ */ jsxRuntime.jsx(CallConversationEmpty, { callExtId: recordingsCallExtId }),
|
|
282
|
-
(hasTranscript || recordingsCallExtId) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-0 z-10 flex justify-center py-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
283
|
-
chunkZBP4ZSAJ_cjs.ConversationFilter,
|
|
284
|
-
{
|
|
285
|
-
value: view,
|
|
286
|
-
options: filterOptions,
|
|
287
|
-
onChange: setView
|
|
288
|
-
}
|
|
289
|
-
) }),
|
|
290
|
-
view === "recordings" && recordingsCallExtId && /* @__PURE__ */ jsxRuntime.jsx(chunkVIRQYEFL_cjs.RecordingsList, { callExtId: recordingsCallExtId, title: meetingTitle, className: "py-1" }),
|
|
291
|
-
loadOlder,
|
|
292
|
-
view === "transcript" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col py-1", "data-testid": "transcript-view", children: [
|
|
293
|
-
isHost && /* @__PURE__ */ jsxRuntime.jsx(
|
|
294
|
-
chunkVIRQYEFL_cjs.SaveTranscriptToThread,
|
|
295
|
-
{
|
|
296
|
-
title: meetingTitle,
|
|
297
|
-
lines: transcriptExport,
|
|
298
|
-
className: "mx-3 mb-2 self-start"
|
|
299
|
-
}
|
|
300
|
-
),
|
|
301
|
-
transcriptMessages.map((msg) => transcriptEntry(msg)),
|
|
302
|
-
/* @__PURE__ */ jsxRuntime.jsx(ProvisionalSpeakers, { ids: provisionalSpeakers })
|
|
303
|
-
] }),
|
|
304
|
-
(view === "all" || view === "chat") && items.map((item, i) => {
|
|
305
|
-
const { message: msg, isFirstOfDay } = item;
|
|
306
|
-
const deleted = !!msg.deleted;
|
|
307
|
-
if (deleted && isTranscriptMessage(msg)) return null;
|
|
308
|
-
const separator = isFirstOfDay && /* @__PURE__ */ jsxRuntime.jsx(react.DateSeparator, { children: formatDay(msg.created_at) });
|
|
309
|
-
if (isTranscriptMessage(msg)) {
|
|
310
|
-
if (view === "chat") return null;
|
|
311
|
-
const superseded = supersededTranscript.has(msg);
|
|
312
|
-
if (superseded && !isFirstOfDay) return null;
|
|
313
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Fragment, { children: [
|
|
314
|
-
separator,
|
|
315
|
-
!superseded && transcriptEntry(msg)
|
|
316
|
-
] }, msg.external_id);
|
|
317
|
-
}
|
|
318
|
-
if (msg.kind === "recording" && msg.call_ext_id && !deleted) {
|
|
319
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Fragment, { children: [
|
|
320
|
-
separator,
|
|
321
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
322
|
-
chunkVIRQYEFL_cjs.RecordingCard,
|
|
323
|
-
{
|
|
324
|
-
callExtId: msg.call_ext_id,
|
|
325
|
-
recordingExtId: msg.recording_ext_id ?? null,
|
|
326
|
-
title: meetingTitle,
|
|
327
|
-
time: formatTime(msg.created_at)
|
|
328
|
-
}
|
|
329
|
-
)
|
|
330
|
-
] }, msg.external_id);
|
|
331
|
-
}
|
|
332
|
-
if (msg.kind === "call" && msg.call_ext_id && !deleted) {
|
|
333
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Fragment, { children: [
|
|
334
|
-
separator,
|
|
335
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
336
|
-
ChatCallCard,
|
|
337
|
-
{
|
|
338
|
-
callExtId: msg.call_ext_id,
|
|
339
|
-
senderName: msg.sender_ext_id ? senderName(msg.sender_ext_id) : null,
|
|
340
|
-
latest: latestCallCards.has(msg.external_id),
|
|
341
|
-
name: senderName,
|
|
342
|
-
time: formatTime(msg.created_at)
|
|
343
|
-
}
|
|
344
|
-
)
|
|
345
|
-
] }, msg.external_id);
|
|
346
|
-
}
|
|
347
|
-
return renderItem(item, i);
|
|
348
|
-
}),
|
|
349
|
-
view === "all" && /* @__PURE__ */ jsxRuntime.jsx(ProvisionalSpeakers, { ids: provisionalSpeakers })
|
|
350
|
-
] });
|
|
351
|
-
}
|
|
352
|
-
function StartCallButton(props) {
|
|
353
|
-
const enabled = react.useCallsEnabled();
|
|
354
|
-
const canHost = react.useCanHostCalls();
|
|
355
|
-
return enabled && (canHost || props.isLive) ? /* @__PURE__ */ jsxRuntime.jsx(EnabledStartCallButton, { ...props }) : null;
|
|
356
|
-
}
|
|
357
|
-
function EnabledStartCallButton({
|
|
358
|
-
onStart,
|
|
359
|
-
isLive = false,
|
|
360
|
-
label = "Start call",
|
|
361
|
-
testId = "start-call-button"
|
|
362
|
-
}) {
|
|
363
|
-
const [isStarting, setIsStarting] = react$1.useState(false);
|
|
364
|
-
const inCall = react.useCallSession((s) => s.active !== null);
|
|
365
|
-
const text = inCall ? "Already in a call" : isLive ? "Join call" : label;
|
|
366
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Tooltip, { children: [
|
|
367
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
368
|
-
ui.Button,
|
|
369
|
-
{
|
|
370
|
-
type: "button",
|
|
371
|
-
variant: "ghost",
|
|
372
|
-
size: "icon",
|
|
373
|
-
"aria-label": isLive ? "Join call" : label,
|
|
374
|
-
"data-testid": testId,
|
|
375
|
-
"data-live": isLive || void 0,
|
|
376
|
-
disabled: isStarting || inCall,
|
|
377
|
-
onClick: () => {
|
|
378
|
-
setIsStarting(true);
|
|
379
|
-
void onStart().finally(() => setIsStarting(false));
|
|
380
|
-
},
|
|
381
|
-
className: ui.cn(
|
|
382
|
-
"text-muted-foreground hover:text-foreground",
|
|
383
|
-
isLive && "text-green-text hover:text-green-text"
|
|
384
|
-
),
|
|
385
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Phone, { className: ui.cn("size-5", isLive && "animate-pulse") })
|
|
386
|
-
}
|
|
387
|
-
) }),
|
|
388
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.TooltipContent, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: text }) })
|
|
389
|
-
] });
|
|
390
|
-
}
|
|
391
|
-
function DmCallButton({ peer }) {
|
|
392
|
-
const arbi = react.useArbi();
|
|
393
|
-
const name = react.userDisplayName(peer);
|
|
394
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
395
|
-
StartCallButton,
|
|
396
|
-
{
|
|
397
|
-
onStart: () => react.startDmCall(arbi, {
|
|
398
|
-
external_id: peer.external_id,
|
|
399
|
-
encryption_public_key: peer.encryption_public_key ?? null,
|
|
400
|
-
name
|
|
401
|
-
}),
|
|
402
|
-
label: `Call ${name}`,
|
|
403
|
-
testId: "dm-call-button"
|
|
404
|
-
}
|
|
405
|
-
);
|
|
406
|
-
}
|
|
407
|
-
var INVITE_LINK_HINT = "will get an invitation to create an ARBI account and join";
|
|
408
|
-
var NO_KEY_REASON = "Cannot receive encrypted calls yet";
|
|
409
|
-
var NO_EMAIL_REASON = "No e-mail address to send a link to";
|
|
410
|
-
function contactName(contact) {
|
|
411
|
-
return contact.card?.name?.trim() || [contact.card?.given_name, contact.card?.family_name].filter(Boolean).join(" ") || (contact.user ? ui.getUserDisplayName(contact.user) : "") || contactEmail(contact) || "Contact";
|
|
412
|
-
}
|
|
413
|
-
function contactEmail(contact) {
|
|
414
|
-
return contact.email ?? contact.user?.email ?? contact.card?.emails?.[0]?.email ?? null;
|
|
415
|
-
}
|
|
416
|
-
function callContactOf(contact) {
|
|
417
|
-
if (!contact.external_id || contact.status === "failed") return null;
|
|
418
|
-
if (contact.user && ui.isAgent(contact.user)) return null;
|
|
419
|
-
return {
|
|
420
|
-
contactExtId: contact.external_id,
|
|
421
|
-
user: contact.user ?? null,
|
|
422
|
-
name: contactName(contact),
|
|
423
|
-
email: contactEmail(contact)
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
function userCandidate(user, section, status, contactExtId = null) {
|
|
427
|
-
const ringable = status !== "ring" || !!user.encryption_public_key;
|
|
428
|
-
return {
|
|
429
|
-
id: user.external_id,
|
|
430
|
-
name: ui.getUserDisplayName(user) || user.email,
|
|
431
|
-
email: user.email ?? null,
|
|
432
|
-
section,
|
|
433
|
-
status: ringable ? status : "unavailable",
|
|
434
|
-
reason: ringable ? void 0 : NO_KEY_REASON,
|
|
435
|
-
user,
|
|
436
|
-
contactExtId
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
function buildCallCandidates(opts) {
|
|
440
|
-
const seen = /* @__PURE__ */ new Set();
|
|
441
|
-
const out = [];
|
|
442
|
-
const add = (c) => {
|
|
443
|
-
if (seen.has(c.id)) return;
|
|
444
|
-
seen.add(c.id);
|
|
445
|
-
out.push(c);
|
|
446
|
-
};
|
|
447
|
-
const people = (users) => users.filter((u) => !ui.isAgent(u) && u.external_id !== opts.me);
|
|
448
|
-
if (opts.scope !== "contacts") {
|
|
449
|
-
for (const u of people(opts.members)) add(userCandidate(u, "members", "ring"));
|
|
450
|
-
return out;
|
|
451
|
-
}
|
|
452
|
-
const contacts = (opts.contacts ?? []).filter((c) => !(c.user && ui.isAgent(c.user)));
|
|
453
|
-
const contactOf = new Map(
|
|
454
|
-
contacts.filter((c) => c.user).map((c) => [c.user.external_id, c.contactExtId])
|
|
455
|
-
);
|
|
456
|
-
for (const u of people(opts.members)) {
|
|
457
|
-
const contactId = contactOf.get(u.external_id) ?? opts.contactIdOf?.(u) ?? null;
|
|
458
|
-
add(userCandidate(u, "members", contactId ? "ring" : "add-contact", contactId));
|
|
459
|
-
}
|
|
460
|
-
for (const c of contacts) {
|
|
461
|
-
if (c.user) {
|
|
462
|
-
if (c.user.external_id === opts.me) continue;
|
|
463
|
-
add(userCandidate(c.user, "contacts", "ring", c.contactExtId));
|
|
464
|
-
continue;
|
|
465
|
-
}
|
|
466
|
-
const status = c.email ? "invite" : "unavailable";
|
|
467
|
-
add({
|
|
468
|
-
id: c.contactExtId,
|
|
469
|
-
name: c.name,
|
|
470
|
-
email: c.email,
|
|
471
|
-
section: "contacts",
|
|
472
|
-
status,
|
|
473
|
-
reason: c.email ? INVITE_LINK_HINT : NO_EMAIL_REASON,
|
|
474
|
-
user: null,
|
|
475
|
-
contactExtId: c.contactExtId
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
return out;
|
|
479
|
-
}
|
|
480
|
-
function isPickable(c) {
|
|
481
|
-
return c.status === "ring" || c.status === "invite";
|
|
482
|
-
}
|
|
483
|
-
function matchesQuery(c, query) {
|
|
484
|
-
const q = query.trim().toLowerCase();
|
|
485
|
-
if (!q) return true;
|
|
486
|
-
return c.name.toLowerCase().includes(q) || (c.email ?? "").toLowerCase().includes(q);
|
|
487
|
-
}
|
|
488
|
-
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
489
|
-
var COPY = {
|
|
490
|
-
workspace: {
|
|
491
|
-
title: "Call thread members",
|
|
492
|
-
description: "Only members of this thread\u2019s workspace can join. Pick who to ring \u2014 or nobody, and share the call from the thread.",
|
|
493
|
-
action: "Start call"
|
|
494
|
-
},
|
|
495
|
-
chat: {
|
|
496
|
-
title: "Call the group",
|
|
497
|
-
description: "The people you pick are rung.",
|
|
498
|
-
action: "Start call"
|
|
499
|
-
},
|
|
500
|
-
contacts: {
|
|
501
|
-
title: "New call",
|
|
502
|
-
description: "Your contacts with an ARBI account are rung. Others get an invitation to create an account and join.",
|
|
503
|
-
action: "Start call"
|
|
504
|
-
}
|
|
505
|
-
};
|
|
506
|
-
function CandidateRow({
|
|
507
|
-
candidate,
|
|
508
|
-
checked,
|
|
509
|
-
onToggle,
|
|
510
|
-
onAddContact,
|
|
511
|
-
adding
|
|
512
|
-
}) {
|
|
513
|
-
const pickable = isPickable(candidate);
|
|
514
|
-
const hint = candidate.status === "invite" ? candidate.reason : candidate.status === "add-contact" ? "Not in your contacts" : void 0;
|
|
515
|
-
const row = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
516
|
-
"li",
|
|
517
|
-
{
|
|
518
|
-
className: ui.cn(
|
|
519
|
-
"flex items-center gap-3 rounded-md px-2 py-1.5",
|
|
520
|
-
pickable ? "hover:bg-muted" : "opacity-60"
|
|
521
|
-
),
|
|
522
|
-
"data-testid": `call-picker-row-${candidate.id}`,
|
|
523
|
-
"data-status": candidate.status,
|
|
524
|
-
"aria-disabled": !pickable || void 0,
|
|
525
|
-
children: [
|
|
526
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
527
|
-
ui.Checkbox,
|
|
528
|
-
{
|
|
529
|
-
checked,
|
|
530
|
-
disabled: !pickable,
|
|
531
|
-
onCheckedChange: onToggle,
|
|
532
|
-
"aria-label": `Invite ${candidate.name}`,
|
|
533
|
-
"data-testid": `call-picker-check-${candidate.id}`
|
|
534
|
-
}
|
|
535
|
-
),
|
|
536
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
537
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate text-sm", children: candidate.name }),
|
|
538
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "block truncate text-xs text-muted-foreground", children: [
|
|
539
|
-
candidate.email,
|
|
540
|
-
hint && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-1 inline-flex items-center gap-1", children: [
|
|
541
|
-
candidate.status === "invite" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Mail, { className: "size-3", "aria-hidden": true }),
|
|
542
|
-
candidate.email ? `\xB7 ${hint}` : hint
|
|
543
|
-
] })
|
|
544
|
-
] })
|
|
545
|
-
] }),
|
|
546
|
-
candidate.status === "add-contact" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
547
|
-
ui.Button,
|
|
548
|
-
{
|
|
549
|
-
type: "button",
|
|
550
|
-
size: "sm",
|
|
551
|
-
variant: "outline",
|
|
552
|
-
disabled: adding,
|
|
553
|
-
onClick: onAddContact,
|
|
554
|
-
"data-testid": `call-picker-add-${candidate.id}`,
|
|
555
|
-
children: [
|
|
556
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserPlus, { className: "mr-1 size-3.5" }),
|
|
557
|
-
"Add contact"
|
|
558
|
-
]
|
|
559
|
-
}
|
|
560
|
-
)
|
|
561
|
-
]
|
|
562
|
-
}
|
|
563
|
-
);
|
|
564
|
-
if (candidate.status !== "unavailable" || !candidate.reason) return row;
|
|
565
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Tooltip, { children: [
|
|
566
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.TooltipTrigger, { asChild: true, children: row }),
|
|
567
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.TooltipContent, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: candidate.reason }) })
|
|
568
|
-
] });
|
|
218
|
+
if (candidate.status !== "unavailable" || !candidate.reason) return row;
|
|
219
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Tooltip, { children: [
|
|
220
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.TooltipTrigger, { asChild: true, children: row }),
|
|
221
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.TooltipContent, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: candidate.reason }) })
|
|
222
|
+
] });
|
|
569
223
|
}
|
|
570
224
|
function InviteLinks({ callExtId }) {
|
|
571
225
|
const { notify } = chunkUIXY4HKM_cjs.useBlocksEnvironment();
|
|
@@ -828,6 +482,48 @@ function CallPeoplePicker({
|
|
|
828
482
|
] })
|
|
829
483
|
] }) });
|
|
830
484
|
}
|
|
485
|
+
function ThreadCallButton({
|
|
486
|
+
conversationId
|
|
487
|
+
}) {
|
|
488
|
+
const arbi = react.useArbi();
|
|
489
|
+
const { data: conversations } = chunkBFKTZUFT_cjs.useConnectedConversations();
|
|
490
|
+
const { workspaceId: workspaceExtId } = chunkWV65MJ43_cjs.useConnectedWorkspace();
|
|
491
|
+
const liveCallId = react.useCallSession((s) => react.threadLiveCallId(s, conversationId));
|
|
492
|
+
const isLive = liveCallId !== null;
|
|
493
|
+
const canHost = react.useCanHostCalls();
|
|
494
|
+
const [picking, setPicking] = react$1.useState(false);
|
|
495
|
+
const conversation = conversations.find((c) => c.external_id === conversationId);
|
|
496
|
+
if (!conversation?.is_shared) return null;
|
|
497
|
+
const title = conversation.title ?? null;
|
|
498
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
499
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
500
|
+
StartCallButton,
|
|
501
|
+
{
|
|
502
|
+
onStart: async () => {
|
|
503
|
+
if (liveCallId && !canHost) return react.openCall(arbi, { callExtId: liveCallId });
|
|
504
|
+
if (isLive) return react.startThreadCall(arbi, { threadExtId: conversationId, title, ring: [] });
|
|
505
|
+
setPicking(true);
|
|
506
|
+
return true;
|
|
507
|
+
},
|
|
508
|
+
isLive,
|
|
509
|
+
label: "Call thread members",
|
|
510
|
+
testId: "thread-call-button"
|
|
511
|
+
}
|
|
512
|
+
),
|
|
513
|
+
picking && /* @__PURE__ */ jsxRuntime.jsx(
|
|
514
|
+
CallPeoplePicker,
|
|
515
|
+
{
|
|
516
|
+
open: true,
|
|
517
|
+
onOpenChange: setPicking,
|
|
518
|
+
scope: "workspace",
|
|
519
|
+
workspaceExtId,
|
|
520
|
+
onSubmit: async ({ ring }) => {
|
|
521
|
+
await react.startThreadCall(arbi, { threadExtId: conversationId, title, ring });
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
)
|
|
525
|
+
] });
|
|
526
|
+
}
|
|
831
527
|
function GroupCallButton({
|
|
832
528
|
chatExtId,
|
|
833
529
|
title,
|
|
@@ -870,6 +566,22 @@ function GroupCallButton({
|
|
|
870
566
|
)
|
|
871
567
|
] });
|
|
872
568
|
}
|
|
569
|
+
function DmCallButton({ peer }) {
|
|
570
|
+
const arbi = react.useArbi();
|
|
571
|
+
const name = react.userDisplayName(peer);
|
|
572
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
573
|
+
StartCallButton,
|
|
574
|
+
{
|
|
575
|
+
onStart: () => react.startDmCall(arbi, {
|
|
576
|
+
external_id: peer.external_id,
|
|
577
|
+
encryption_public_key: peer.encryption_public_key ?? null,
|
|
578
|
+
name
|
|
579
|
+
}),
|
|
580
|
+
label: `Call ${name}`,
|
|
581
|
+
testId: "dm-call-button"
|
|
582
|
+
}
|
|
583
|
+
);
|
|
584
|
+
}
|
|
873
585
|
function NewCallChip() {
|
|
874
586
|
return react.useCanHostCalls() ? /* @__PURE__ */ jsxRuntime.jsx(EnabledNewCallChip, {}) : null;
|
|
875
587
|
}
|
|
@@ -878,235 +590,523 @@ function EnabledNewCallChip() {
|
|
|
878
590
|
const inCall = react.useCallSession((s) => s.active !== null);
|
|
879
591
|
const [open, setOpen] = react$1.useState(false);
|
|
880
592
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
881
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
882
|
-
chunkMOIZ2R5X_cjs.DmInviteChip,
|
|
593
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
594
|
+
chunkMOIZ2R5X_cjs.DmInviteChip,
|
|
595
|
+
{
|
|
596
|
+
testId: "dm-new-call-chip",
|
|
597
|
+
title: "New call",
|
|
598
|
+
description: inCall ? "You are already in a call" : "Call people from your contacts",
|
|
599
|
+
onClick: () => !inCall && setOpen(true)
|
|
600
|
+
}
|
|
601
|
+
),
|
|
602
|
+
open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
603
|
+
CallPeoplePicker,
|
|
604
|
+
{
|
|
605
|
+
open: true,
|
|
606
|
+
onOpenChange: setOpen,
|
|
607
|
+
scope: "contacts",
|
|
608
|
+
onSubmit: async ({ ring, invites }) => {
|
|
609
|
+
await react.startContactsCall(arbi, {
|
|
610
|
+
title: chunk5HEMXXHR_cjs.contactsCallTitle([
|
|
611
|
+
...ring.map((u) => ui.getUserDisplayName(u)),
|
|
612
|
+
...invites.map((g) => g.name)
|
|
613
|
+
]),
|
|
614
|
+
ring,
|
|
615
|
+
invites
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
)
|
|
620
|
+
] });
|
|
621
|
+
}
|
|
622
|
+
function ScheduleCallButton({
|
|
623
|
+
conversationId,
|
|
624
|
+
peer,
|
|
625
|
+
variant = "icon",
|
|
626
|
+
className
|
|
627
|
+
}) {
|
|
628
|
+
const callsEnabled = react.useCanHostCalls();
|
|
629
|
+
const { conversations } = react.useConversationItems();
|
|
630
|
+
const { data: workspaces = [] } = react.useWorkspaces();
|
|
631
|
+
const { workspaceId: selectedWorkspaceId, userId: me } = chunkWV65MJ43_cjs.useConnectedWorkspace();
|
|
632
|
+
const { openCalendar } = chunkUIXY4HKM_cjs.useBlocksEnvironment();
|
|
633
|
+
if (!callsEnabled) return null;
|
|
634
|
+
const open = () => {
|
|
635
|
+
const conversation = conversationId ? conversations?.find((c) => c.external_id === conversationId) : void 0;
|
|
636
|
+
let people = [];
|
|
637
|
+
if (peer) people = [peer];
|
|
638
|
+
else if (conversation?.is_shared) {
|
|
639
|
+
const workspace = workspaces.find((w) => w.external_id === selectedWorkspaceId);
|
|
640
|
+
people = (workspace?.users ?? []).map((wu) => wu.user);
|
|
641
|
+
}
|
|
642
|
+
chunkUIXY4HKM_cjs.requestCalendarComposer({
|
|
643
|
+
title: peer ? `Call with ${ui.getUserDisplayName(peer) || peer.email}` : conversation?.title ?? "",
|
|
644
|
+
conversationId: conversationId ?? null,
|
|
645
|
+
attendees: people.filter((u) => !ui.isAgent(u) && u.external_id !== me).map((u) => ({
|
|
646
|
+
email: u.email,
|
|
647
|
+
user_id: u.external_id,
|
|
648
|
+
name: ui.getUserDisplayName(u) || null
|
|
649
|
+
})),
|
|
650
|
+
addCall: true
|
|
651
|
+
});
|
|
652
|
+
openCalendar();
|
|
653
|
+
};
|
|
654
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
655
|
+
ui.Button,
|
|
656
|
+
{
|
|
657
|
+
type: "button",
|
|
658
|
+
variant: "ghost",
|
|
659
|
+
size: variant === "icon" ? "icon" : "sm",
|
|
660
|
+
className: ui.cn(variant === "icon" && "size-8", className),
|
|
661
|
+
onClick: open,
|
|
662
|
+
"aria-label": "Schedule call",
|
|
663
|
+
title: "Schedule call",
|
|
664
|
+
"data-testid": "schedule-call-button",
|
|
665
|
+
children: [
|
|
666
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CalendarPlus, { className: "size-4" }),
|
|
667
|
+
variant === "label" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1.5", children: "Schedule call" })
|
|
668
|
+
]
|
|
669
|
+
}
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
function useMeetingThreadMessages(meetingCallExtId, messageHistory) {
|
|
673
|
+
const hasRecTranscript = react$1.useMemo(
|
|
674
|
+
() => !!meetingCallExtId && react.hasRecordingTranscript(messageHistory, react.threadTranscriptRef),
|
|
675
|
+
[meetingCallExtId, messageHistory]
|
|
676
|
+
);
|
|
677
|
+
const recordingWindows = react.useRecordingWindows(meetingCallExtId, hasRecTranscript);
|
|
678
|
+
return react$1.useMemo(
|
|
679
|
+
() => hasRecTranscript ? react.supersedeLiveTranscript(messageHistory, react.threadTranscriptRef, recordingWindows) : messageHistory,
|
|
680
|
+
[hasRecTranscript, messageHistory, recordingWindows]
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
function MeetingThreadTranscriptAction({
|
|
684
|
+
conversationExtId,
|
|
685
|
+
meetingCallExtId,
|
|
686
|
+
title,
|
|
687
|
+
messages
|
|
688
|
+
}) {
|
|
689
|
+
const { data: call } = react.useCall(meetingCallExtId);
|
|
690
|
+
const { data: workspaceUsers = [] } = react.useWorkspaceUsers();
|
|
691
|
+
const lines = react$1.useMemo(
|
|
692
|
+
() => react.threadTranscriptLines(messages, (id) => {
|
|
693
|
+
const user = workspaceUsers.find((wu) => wu.user.external_id === id)?.user;
|
|
694
|
+
return user ? ui.getUserDisplayName(user) : null;
|
|
695
|
+
}),
|
|
696
|
+
[messages, workspaceUsers]
|
|
697
|
+
);
|
|
698
|
+
if (!meetingCallExtId || !call?.is_creator) return null;
|
|
699
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
700
|
+
chunkF5T4W2R2_cjs.SaveTranscriptToThread,
|
|
701
|
+
{
|
|
702
|
+
title,
|
|
703
|
+
lines,
|
|
704
|
+
excludeConversationExtId: conversationExtId,
|
|
705
|
+
iconOnly: true
|
|
706
|
+
}
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
function MeetingThreadRecordingsAction({
|
|
710
|
+
meetingCallExtId,
|
|
711
|
+
title
|
|
712
|
+
}) {
|
|
713
|
+
const [open, setOpen] = react$1.useState(false);
|
|
714
|
+
const pending = chunkZT5MIFLC_cjs.usePendingRecording();
|
|
715
|
+
react$1.useEffect(() => {
|
|
716
|
+
if (pending) setOpen(true);
|
|
717
|
+
}, [pending]);
|
|
718
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
719
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
720
|
+
chunk5HEMXXHR_cjs.HeaderAction,
|
|
721
|
+
{
|
|
722
|
+
label: "Recordings",
|
|
723
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Disc, { className: "size-3.5", "aria-hidden": true }),
|
|
724
|
+
iconOnly: true,
|
|
725
|
+
onClick: () => setOpen(true),
|
|
726
|
+
testId: "meeting-recordings"
|
|
727
|
+
}
|
|
728
|
+
),
|
|
729
|
+
open && /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, { open: true, onOpenChange: (o) => !o && setOpen(false), children: /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogContent, { className: "sm:max-w-2xl", "data-testid": "meeting-recordings-dialog", children: [
|
|
730
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.DialogHeader, { children: [
|
|
731
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.DialogTitle, { children: "Recordings" }),
|
|
732
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.DialogDescription, { children: "Recordings of this meeting, encrypted under the workspace key. Playing or downloading one decrypts it in this browser." })
|
|
733
|
+
] }),
|
|
734
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
735
|
+
chunkF5T4W2R2_cjs.RecordingsList,
|
|
736
|
+
{
|
|
737
|
+
callExtId: meetingCallExtId,
|
|
738
|
+
title,
|
|
739
|
+
className: "max-h-[60vh] overflow-y-auto"
|
|
740
|
+
}
|
|
741
|
+
)
|
|
742
|
+
] }) })
|
|
743
|
+
] });
|
|
744
|
+
}
|
|
745
|
+
function ConnectedConversationCallActions() {
|
|
746
|
+
const conversationId = react.useArbiSessionState((state) => state.conversationId);
|
|
747
|
+
const { conversations } = react.useConversationItems();
|
|
748
|
+
const conversation = conversationId ? conversations.find((c) => c.external_id === conversationId) : void 0;
|
|
749
|
+
const meetingCallExtId = conversation?.meeting_call_ext_id ?? null;
|
|
750
|
+
const { messageHistory } = react.useConversationData();
|
|
751
|
+
const threadMessages = useMeetingThreadMessages(meetingCallExtId, messageHistory);
|
|
752
|
+
const meetingMessages = react$1.useMemo(
|
|
753
|
+
() => meetingCallExtId ? threadMessages.map((m) => ({
|
|
754
|
+
content: m.content,
|
|
755
|
+
created_at: m.created_at,
|
|
756
|
+
tools: m.tools ?? m.meta?.tools
|
|
757
|
+
})) : [],
|
|
758
|
+
[meetingCallExtId, threadMessages]
|
|
759
|
+
);
|
|
760
|
+
if (!conversationId) return null;
|
|
761
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
762
|
+
/* @__PURE__ */ jsxRuntime.jsx(ThreadCallButton, { conversationId }),
|
|
763
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScheduleCallButton, { conversationId }),
|
|
764
|
+
meetingCallExtId && /* @__PURE__ */ jsxRuntime.jsx(
|
|
765
|
+
MeetingThreadTranscriptAction,
|
|
883
766
|
{
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
767
|
+
conversationExtId: conversationId,
|
|
768
|
+
meetingCallExtId,
|
|
769
|
+
title: conversation?.title,
|
|
770
|
+
messages: meetingMessages
|
|
888
771
|
}
|
|
889
772
|
),
|
|
890
|
-
|
|
891
|
-
|
|
773
|
+
meetingCallExtId && /* @__PURE__ */ jsxRuntime.jsx(
|
|
774
|
+
MeetingThreadRecordingsAction,
|
|
892
775
|
{
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
scope: "contacts",
|
|
896
|
-
onSubmit: async ({ ring, invites }) => {
|
|
897
|
-
await react.startContactsCall(arbi, {
|
|
898
|
-
title: chunkUAF2J7P7_cjs.contactsCallTitle([
|
|
899
|
-
...ring.map((u) => ui.getUserDisplayName(u)),
|
|
900
|
-
...invites.map((g) => g.name)
|
|
901
|
-
]),
|
|
902
|
-
ring,
|
|
903
|
-
invites
|
|
904
|
-
});
|
|
905
|
-
}
|
|
776
|
+
meetingCallExtId,
|
|
777
|
+
title: conversation?.title
|
|
906
778
|
}
|
|
907
779
|
)
|
|
908
780
|
] });
|
|
909
781
|
}
|
|
910
|
-
function
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
782
|
+
function ChatCallCard({
|
|
783
|
+
callExtId,
|
|
784
|
+
senderName,
|
|
785
|
+
latest,
|
|
786
|
+
name,
|
|
787
|
+
time
|
|
915
788
|
}) {
|
|
916
|
-
const
|
|
917
|
-
const {
|
|
918
|
-
const
|
|
919
|
-
const
|
|
920
|
-
const
|
|
921
|
-
|
|
922
|
-
const
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
email: u.email,
|
|
935
|
-
user_id: u.external_id,
|
|
936
|
-
name: ui.getUserDisplayName(u) || null
|
|
937
|
-
})),
|
|
938
|
-
addCall: true
|
|
939
|
-
});
|
|
940
|
-
openCalendar();
|
|
941
|
-
};
|
|
789
|
+
const arbi = react.useArbi();
|
|
790
|
+
const { data: call } = react.useCall(latest ? callExtId : null);
|
|
791
|
+
const liveNow = react.useCallSession((s) => callExtId in s.liveCalls);
|
|
792
|
+
const inThisCall = react.useCallSession((s) => s.active?.callExtId === callExtId);
|
|
793
|
+
const inAnotherCall = react.useCallSession((s) => !!s.active && s.active.callExtId !== callExtId);
|
|
794
|
+
const [busy, setBusy] = react$1.useState(false);
|
|
795
|
+
const live = latest && chunk5HEMXXHR_cjs.isCallLive(call, liveNow);
|
|
796
|
+
let summary;
|
|
797
|
+
if (live) summary = senderName ? `${senderName} started a call` : "Call in progress";
|
|
798
|
+
else if (latest && call?.started_at && call.ended_at) {
|
|
799
|
+
const seconds = (Date.parse(call.ended_at) - Date.parse(call.started_at)) / 1e3;
|
|
800
|
+
const joined = (call.last_participants ?? []).map(name);
|
|
801
|
+
summary = [
|
|
802
|
+
"Call",
|
|
803
|
+
chunk5HEMXXHR_cjs.formatCallDuration(seconds),
|
|
804
|
+
joined.length ? `joined ${joined.join(", ")}` : null
|
|
805
|
+
].filter(Boolean).join(" \xB7 ");
|
|
806
|
+
} else summary = senderName ? `Call started by ${senderName}` : "Call";
|
|
942
807
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
943
|
-
|
|
808
|
+
"div",
|
|
944
809
|
{
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
className: ui.cn(variant === "icon" && "size-8", className),
|
|
949
|
-
onClick: open,
|
|
950
|
-
"aria-label": "Schedule call",
|
|
951
|
-
title: "Schedule call",
|
|
952
|
-
"data-testid": "schedule-call-button",
|
|
810
|
+
className: "mx-auto my-2 flex w-fit max-w-full flex-wrap items-center justify-center gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs",
|
|
811
|
+
"data-testid": "chat-call-card",
|
|
812
|
+
"data-live": live || void 0,
|
|
953
813
|
children: [
|
|
954
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.
|
|
955
|
-
|
|
814
|
+
live ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Phone, { className: "size-4 animate-pulse text-green-text", "aria-hidden": true }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PhoneOff, { className: "size-4 text-muted-foreground", "aria-hidden": true }),
|
|
815
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-testid": "chat-call-card-summary", children: summary }),
|
|
816
|
+
time && /* @__PURE__ */ jsxRuntime.jsx("time", { className: "text-muted-foreground", children: time }),
|
|
817
|
+
live && /* @__PURE__ */ jsxRuntime.jsx(
|
|
818
|
+
ui.Button,
|
|
819
|
+
{
|
|
820
|
+
type: "button",
|
|
821
|
+
size: "sm",
|
|
822
|
+
className: "h-7 bg-green-600 text-white hover:bg-green-700",
|
|
823
|
+
disabled: busy || inThisCall || inAnotherCall,
|
|
824
|
+
title: inAnotherCall ? "You are already in a call" : void 0,
|
|
825
|
+
onClick: () => {
|
|
826
|
+
setBusy(true);
|
|
827
|
+
void react.openCall(arbi, { callExtId }).finally(() => setBusy(false));
|
|
828
|
+
},
|
|
829
|
+
"data-testid": "chat-call-card-join",
|
|
830
|
+
children: inThisCall ? "In call" : "Join"
|
|
831
|
+
}
|
|
832
|
+
)
|
|
956
833
|
]
|
|
957
834
|
}
|
|
958
835
|
);
|
|
959
836
|
}
|
|
960
|
-
function
|
|
837
|
+
function useCallPersonName(identity, fallbackName) {
|
|
838
|
+
const arbi = react.useArbi();
|
|
839
|
+
const { byId } = react.usePeople();
|
|
840
|
+
const me = arbi.isLoggedIn && arbi.user.identity()?.externalId === identity;
|
|
841
|
+
const profile = me ? arbi.user.profile() : null;
|
|
842
|
+
return react$1.useMemo(() => {
|
|
843
|
+
if (profile)
|
|
844
|
+
return ui.getUserDisplayName({ given_name: profile.givenName, family_name: profile.familyName });
|
|
845
|
+
const user = byId(identity);
|
|
846
|
+
if (user) return ui.getUserDisplayName(user);
|
|
847
|
+
return (fallbackName || identity).trim().split(/\s+/).join(" ");
|
|
848
|
+
}, [profile, byId, identity, fallbackName]);
|
|
849
|
+
}
|
|
850
|
+
function CallConversationEmpty({ callExtId }) {
|
|
851
|
+
const { inCall, transcribing } = chunkOAIOOVFN_cjs.useMyCallStatus(callExtId);
|
|
852
|
+
const live = react.useCallSession((s) => !!s.liveCalls[callExtId]) || inCall;
|
|
853
|
+
if (!live) {
|
|
854
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
855
|
+
chunkZW6FPIFC_cjs.EmptyState,
|
|
856
|
+
{
|
|
857
|
+
icon: lucideReact.AudioLines,
|
|
858
|
+
title: "No transcript",
|
|
859
|
+
description: "This call was not transcribed. When a call here is transcribed, what people say appears in this conversation.",
|
|
860
|
+
className: "mx-auto my-8 max-w-xl",
|
|
861
|
+
testId: "call-conversation-empty"
|
|
862
|
+
}
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
866
|
+
chunkZW6FPIFC_cjs.EmptyState,
|
|
867
|
+
{
|
|
868
|
+
icon: transcribing ? lucideReact.Captions : lucideReact.CaptionsOff,
|
|
869
|
+
title: "Call in progress \u2014 the transcript will appear here",
|
|
870
|
+
description: transcribing ? "Transcription is on: what people say shows up here as they speak." : "Transcription is off. The host can turn it on with CC in the call.",
|
|
871
|
+
className: "mx-auto my-8 max-w-xl",
|
|
872
|
+
testId: "call-conversation-empty"
|
|
873
|
+
}
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
function ProvisionalRow({ identity }) {
|
|
877
|
+
const name = useCallPersonName(identity);
|
|
878
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
879
|
+
chunkZBP4ZSAJ_cjs.ProvisionalTranscriptLine,
|
|
880
|
+
{
|
|
881
|
+
speakerId: identity,
|
|
882
|
+
speakerName: name,
|
|
883
|
+
speaker: /* @__PURE__ */ jsxRuntime.jsx(chunk5HEMXXHR_cjs.CallUserPill, { identity })
|
|
884
|
+
}
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
function ProvisionalSpeakers({ ids }) {
|
|
888
|
+
if (!ids.length) return null;
|
|
889
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pb-2", "data-testid": "transcript-provisional-rows", children: ids.map((id) => /* @__PURE__ */ jsxRuntime.jsx(ProvisionalRow, { identity: id }, id)) });
|
|
890
|
+
}
|
|
891
|
+
var LINE_WAIT_MS = 1e4;
|
|
892
|
+
var MIN_SPEECH_MS = 800;
|
|
893
|
+
function useProvisionalSpeakers(callExtId, lines) {
|
|
894
|
+
const { inCall, transcribing } = chunkOAIOOVFN_cjs.useMyCallStatus(callExtId);
|
|
895
|
+
const speaking = chunkOAIOOVFN_cjs.useSpeakingIds();
|
|
896
|
+
const pending = react$1.useRef(/* @__PURE__ */ new Map());
|
|
897
|
+
const [, tick] = react$1.useState(0);
|
|
898
|
+
const active = inCall && transcribing;
|
|
899
|
+
const now = Date.now();
|
|
900
|
+
if (active) {
|
|
901
|
+
for (const id of speaking) {
|
|
902
|
+
const p = pending.current.get(id);
|
|
903
|
+
if (p) p.lastHeardAt = now;
|
|
904
|
+
else pending.current.set(id, { startedAt: now, lastHeardAt: now });
|
|
905
|
+
}
|
|
906
|
+
} else if (pending.current.size) {
|
|
907
|
+
pending.current.clear();
|
|
908
|
+
}
|
|
909
|
+
const latest = react$1.useMemo(() => {
|
|
910
|
+
const m = /* @__PURE__ */ new Map();
|
|
911
|
+
for (const l of lines) m.set(l.speakerId, Math.max(m.get(l.speakerId) ?? 0, l.at));
|
|
912
|
+
return m;
|
|
913
|
+
}, [lines]);
|
|
914
|
+
for (const [id, p] of [...pending.current]) {
|
|
915
|
+
const arrived = (latest.get(id) ?? 0) >= p.startedAt - 3e3;
|
|
916
|
+
const stale = !speaking.includes(id) && now - p.lastHeardAt > LINE_WAIT_MS;
|
|
917
|
+
if (arrived && !speaking.includes(id) || stale) pending.current.delete(id);
|
|
918
|
+
else if (arrived) p.startedAt = now;
|
|
919
|
+
}
|
|
920
|
+
const waiting = pending.current.size > 0;
|
|
921
|
+
react$1.useEffect(() => {
|
|
922
|
+
if (!waiting) return;
|
|
923
|
+
const id = setInterval(() => tick((n) => n + 1), 1e3);
|
|
924
|
+
return () => clearInterval(id);
|
|
925
|
+
}, [waiting]);
|
|
926
|
+
return [...pending.current].filter(([, p]) => p.lastHeardAt - p.startedAt >= MIN_SPEECH_MS).map(([id]) => id);
|
|
927
|
+
}
|
|
928
|
+
var { isTranscriptMessage, parseTranscriptContent } = browser.chats;
|
|
929
|
+
function ConnectedCallChatHistory({
|
|
930
|
+
chat,
|
|
931
|
+
messages,
|
|
932
|
+
items,
|
|
933
|
+
renderItem,
|
|
934
|
+
loadOlder,
|
|
935
|
+
memberById,
|
|
936
|
+
senderName,
|
|
937
|
+
myExtId,
|
|
938
|
+
formatTime,
|
|
939
|
+
formatDay
|
|
940
|
+
}) {
|
|
941
|
+
const arbi = react.useArbi();
|
|
942
|
+
const [view, setView] = react$1.useState("all");
|
|
943
|
+
react$1.useEffect(() => setView("all"), [chat?.external_id]);
|
|
944
|
+
const recordingsCallExtId = chat?.call_ext_id ?? null;
|
|
945
|
+
const pendingRecording = chunkZT5MIFLC_cjs.usePendingRecording();
|
|
946
|
+
react$1.useEffect(() => {
|
|
947
|
+
if (pendingRecording && recordingsCallExtId) setView("recordings");
|
|
948
|
+
}, [pendingRecording, recordingsCallExtId]);
|
|
949
|
+
const latestCallCards = react$1.useMemo(() => {
|
|
950
|
+
const latest = /* @__PURE__ */ new Map();
|
|
951
|
+
for (const m of messages)
|
|
952
|
+
if (m.kind === "call" && m.call_ext_id && !m.deleted) latest.set(m.call_ext_id, m.external_id);
|
|
953
|
+
return new Set(latest.values());
|
|
954
|
+
}, [messages]);
|
|
961
955
|
const hasRecTranscript = react$1.useMemo(
|
|
962
|
-
() =>
|
|
963
|
-
[
|
|
956
|
+
() => react.hasRecordingTranscript(messages, react.chatTranscriptRef),
|
|
957
|
+
[messages]
|
|
964
958
|
);
|
|
965
|
-
const recordingWindows = react.useRecordingWindows(
|
|
966
|
-
|
|
967
|
-
() =>
|
|
968
|
-
[
|
|
959
|
+
const recordingWindows = react.useRecordingWindows(recordingsCallExtId, hasRecTranscript);
|
|
960
|
+
const supersededTranscript = react$1.useMemo(
|
|
961
|
+
() => react.supersededTranscriptLines(messages, react.chatTranscriptRef, recordingWindows),
|
|
962
|
+
[messages, recordingWindows]
|
|
969
963
|
);
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
}) {
|
|
974
|
-
const arbi = react.useArbi();
|
|
975
|
-
const { data: conversations } = chunkBFKTZUFT_cjs.useConnectedConversations();
|
|
976
|
-
const { workspaceId: workspaceExtId } = chunkWV65MJ43_cjs.useConnectedWorkspace();
|
|
977
|
-
const liveCallId = react.useCallSession((s) => react.threadLiveCallId(s, conversationId));
|
|
978
|
-
const isLive = liveCallId !== null;
|
|
979
|
-
const canHost = react.useCanHostCalls();
|
|
980
|
-
const [picking, setPicking] = react$1.useState(false);
|
|
981
|
-
const conversation = conversations.find((c) => c.external_id === conversationId);
|
|
982
|
-
if (!conversation?.is_shared) return null;
|
|
983
|
-
const title = conversation.title ?? null;
|
|
984
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
985
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
986
|
-
StartCallButton,
|
|
987
|
-
{
|
|
988
|
-
onStart: async () => {
|
|
989
|
-
if (liveCallId && !canHost) return react.openCall(arbi, { callExtId: liveCallId });
|
|
990
|
-
if (isLive) return react.startThreadCall(arbi, { threadExtId: conversationId, title, ring: [] });
|
|
991
|
-
setPicking(true);
|
|
992
|
-
return true;
|
|
993
|
-
},
|
|
994
|
-
isLive,
|
|
995
|
-
label: "Call thread members",
|
|
996
|
-
testId: "thread-call-button"
|
|
997
|
-
}
|
|
964
|
+
const transcriptMessages = react$1.useMemo(
|
|
965
|
+
() => react.sortTranscriptMessages(
|
|
966
|
+
messages.filter((m) => isTranscriptMessage(m) && !m.deleted && !supersededTranscript.has(m))
|
|
998
967
|
),
|
|
999
|
-
|
|
1000
|
-
|
|
968
|
+
[messages, supersededTranscript]
|
|
969
|
+
);
|
|
970
|
+
const hasTranscript = transcriptMessages.length > 0;
|
|
971
|
+
const { data: meetingCall } = react.useCall(hasTranscript ? chat?.call_ext_id : null);
|
|
972
|
+
const isHost = !!meetingCall?.is_creator;
|
|
973
|
+
const [meetingTitle, setMeetingTitle] = react$1.useState(null);
|
|
974
|
+
react$1.useEffect(() => {
|
|
975
|
+
if (!chat || !isHost && !recordingsCallExtId) return;
|
|
976
|
+
let cancelled = false;
|
|
977
|
+
arbi.chats.title(chat).then((t) => !cancelled && setMeetingTitle(t)).catch(() => void 0);
|
|
978
|
+
return () => {
|
|
979
|
+
cancelled = true;
|
|
980
|
+
};
|
|
981
|
+
}, [arbi, isHost, chat, recordingsCallExtId]);
|
|
982
|
+
const transcriptSpeaker = (msg) => {
|
|
983
|
+
const parsed = msg.decryptFailed ? null : parseTranscriptContent(msg.content);
|
|
984
|
+
return { parsed, speakerId: parsed?.speaker_identity || msg.sender_ext_id || "" };
|
|
985
|
+
};
|
|
986
|
+
const transcriptExport = react$1.useMemo(
|
|
987
|
+
() => transcriptMessages.filter((m) => !m.decryptFailed).map((m) => {
|
|
988
|
+
const parsed = parseTranscriptContent(m.content);
|
|
989
|
+
const speakerId = parsed?.speaker_identity || m.sender_ext_id || "";
|
|
990
|
+
return {
|
|
991
|
+
speaker: parsed?.speaker_name || (memberById(speakerId) ? senderName(speakerId) : "") || "Former member",
|
|
992
|
+
at: parsed?.started_at ?? m.created_at,
|
|
993
|
+
text: parsed?.text ?? m.content ?? ""
|
|
994
|
+
};
|
|
995
|
+
}),
|
|
996
|
+
[transcriptMessages, memberById, senderName]
|
|
997
|
+
);
|
|
998
|
+
const transcriptLayout = react$1.useMemo(() => {
|
|
999
|
+
const shown = view === "transcript" ? transcriptMessages : messages;
|
|
1000
|
+
const continued = chunkZBP4ZSAJ_cjs.transcriptRuns(
|
|
1001
|
+
shown,
|
|
1002
|
+
(m) => isTranscriptMessage(m) && !supersededTranscript.has(m) ? transcriptSpeaker(m).speakerId : null,
|
|
1003
|
+
(m) => Date.parse(transcriptSpeaker(m).parsed?.started_at ?? m.created_at ?? "") || 0
|
|
1004
|
+
);
|
|
1005
|
+
return { continued };
|
|
1006
|
+
}, [view, messages, transcriptMessages, supersededTranscript]);
|
|
1007
|
+
const transcriptEntry = (msg) => {
|
|
1008
|
+
const { parsed, speakerId } = transcriptSpeaker(msg);
|
|
1009
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1010
|
+
chunkIOCEKN44_cjs.TranscriptEntry,
|
|
1001
1011
|
{
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
meetingCallExtId,
|
|
1016
|
-
title,
|
|
1017
|
-
messages
|
|
1018
|
-
}) {
|
|
1019
|
-
const { data: call } = react.useCall(meetingCallExtId);
|
|
1020
|
-
const { data: workspaceUsers = [] } = react.useWorkspaceUsers();
|
|
1021
|
-
const lines = react$1.useMemo(
|
|
1022
|
-
() => react.threadTranscriptLines(messages, (id) => {
|
|
1023
|
-
const user = workspaceUsers.find((wu) => wu.user.external_id === id)?.user;
|
|
1024
|
-
return user ? ui.getUserDisplayName(user) : null;
|
|
1012
|
+
speakerId,
|
|
1013
|
+
speakerName: speakerId === myExtId ? "Me" : parsed?.speaker_name || (memberById(speakerId) ? senderName(speakerId) : senderName(msg.sender_ext_id)),
|
|
1014
|
+
text: parsed?.text ?? msg.content ?? "",
|
|
1015
|
+
at: parsed?.started_at ?? msg.created_at,
|
|
1016
|
+
continued: transcriptLayout.continued.has(msg)
|
|
1017
|
+
},
|
|
1018
|
+
msg.external_id
|
|
1019
|
+
);
|
|
1020
|
+
};
|
|
1021
|
+
const chatLines = react$1.useMemo(
|
|
1022
|
+
() => transcriptMessages.map((m) => {
|
|
1023
|
+
const { parsed, speakerId } = transcriptSpeaker(m);
|
|
1024
|
+
return { speakerId, at: Date.parse(parsed?.started_at ?? m.created_at ?? "") || 0 };
|
|
1025
1025
|
}),
|
|
1026
|
-
[
|
|
1026
|
+
[transcriptMessages]
|
|
1027
1027
|
);
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1028
|
+
const provisionalSpeakers = useProvisionalSpeakers(recordingsCallExtId, chatLines);
|
|
1029
|
+
const filterOptions = [
|
|
1030
|
+
{ value: "all", label: "All" },
|
|
1031
|
+
{ value: "chat", label: "Chat", testId: "chat-filter" },
|
|
1031
1032
|
{
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
function MeetingThreadRecordingsAction({
|
|
1040
|
-
meetingCallExtId,
|
|
1041
|
-
title
|
|
1042
|
-
}) {
|
|
1043
|
-
const [open, setOpen] = react$1.useState(false);
|
|
1044
|
-
const pending = chunkZT5MIFLC_cjs.usePendingRecording();
|
|
1045
|
-
react$1.useEffect(() => {
|
|
1046
|
-
if (pending) setOpen(true);
|
|
1047
|
-
}, [pending]);
|
|
1033
|
+
value: "transcript",
|
|
1034
|
+
label: "Transcript",
|
|
1035
|
+
count: transcriptMessages.length,
|
|
1036
|
+
testId: "transcript-filter"
|
|
1037
|
+
},
|
|
1038
|
+
...recordingsCallExtId ? [{ value: "recordings", label: "Recordings", testId: "recordings-filter" }] : []
|
|
1039
|
+
];
|
|
1048
1040
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1049
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1050
|
-
|
|
1041
|
+
messages.length === 0 && recordingsCallExtId && /* @__PURE__ */ jsxRuntime.jsx(CallConversationEmpty, { callExtId: recordingsCallExtId }),
|
|
1042
|
+
(hasTranscript || recordingsCallExtId) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-0 z-10 flex justify-center py-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1043
|
+
chunkZBP4ZSAJ_cjs.ConversationFilter,
|
|
1051
1044
|
{
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
onClick: () => setOpen(true),
|
|
1056
|
-
testId: "meeting-recordings"
|
|
1045
|
+
value: view,
|
|
1046
|
+
options: filterOptions,
|
|
1047
|
+
onChange: setView
|
|
1057
1048
|
}
|
|
1058
|
-
),
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1065
|
-
chunkVIRQYEFL_cjs.RecordingsList,
|
|
1049
|
+
) }),
|
|
1050
|
+
view === "recordings" && recordingsCallExtId && /* @__PURE__ */ jsxRuntime.jsx(chunkF5T4W2R2_cjs.RecordingsList, { callExtId: recordingsCallExtId, title: meetingTitle, className: "py-1" }),
|
|
1051
|
+
loadOlder,
|
|
1052
|
+
view === "transcript" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col py-1", "data-testid": "transcript-view", children: [
|
|
1053
|
+
isHost && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1054
|
+
chunkF5T4W2R2_cjs.SaveTranscriptToThread,
|
|
1066
1055
|
{
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
className: "
|
|
1056
|
+
title: meetingTitle,
|
|
1057
|
+
lines: transcriptExport,
|
|
1058
|
+
className: "mx-3 mb-2 self-start"
|
|
1070
1059
|
}
|
|
1071
|
-
)
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
[meetingCallExtId, threadMessages]
|
|
1089
|
-
);
|
|
1090
|
-
if (!conversationId) return null;
|
|
1091
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1092
|
-
/* @__PURE__ */ jsxRuntime.jsx(ThreadCallButton, { conversationId }),
|
|
1093
|
-
/* @__PURE__ */ jsxRuntime.jsx(ScheduleCallButton, { conversationId }),
|
|
1094
|
-
meetingCallExtId && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1095
|
-
MeetingThreadTranscriptAction,
|
|
1096
|
-
{
|
|
1097
|
-
conversationExtId: conversationId,
|
|
1098
|
-
meetingCallExtId,
|
|
1099
|
-
title: conversation?.title,
|
|
1100
|
-
messages: meetingMessages
|
|
1060
|
+
),
|
|
1061
|
+
transcriptMessages.map((msg) => transcriptEntry(msg)),
|
|
1062
|
+
/* @__PURE__ */ jsxRuntime.jsx(ProvisionalSpeakers, { ids: provisionalSpeakers })
|
|
1063
|
+
] }),
|
|
1064
|
+
(view === "all" || view === "chat") && items.map((item, i) => {
|
|
1065
|
+
const { message: msg, isFirstOfDay } = item;
|
|
1066
|
+
const deleted = !!msg.deleted;
|
|
1067
|
+
if (deleted && isTranscriptMessage(msg)) return null;
|
|
1068
|
+
const separator = isFirstOfDay && /* @__PURE__ */ jsxRuntime.jsx(react.DateSeparator, { children: formatDay(msg.created_at) });
|
|
1069
|
+
if (isTranscriptMessage(msg)) {
|
|
1070
|
+
if (view === "chat") return null;
|
|
1071
|
+
const superseded = supersededTranscript.has(msg);
|
|
1072
|
+
if (superseded && !isFirstOfDay) return null;
|
|
1073
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Fragment, { children: [
|
|
1074
|
+
separator,
|
|
1075
|
+
!superseded && transcriptEntry(msg)
|
|
1076
|
+
] }, msg.external_id);
|
|
1101
1077
|
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1078
|
+
if (msg.kind === "recording" && msg.call_ext_id && !deleted) {
|
|
1079
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Fragment, { children: [
|
|
1080
|
+
separator,
|
|
1081
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1082
|
+
chunkF5T4W2R2_cjs.RecordingCard,
|
|
1083
|
+
{
|
|
1084
|
+
callExtId: msg.call_ext_id,
|
|
1085
|
+
recordingExtId: msg.recording_ext_id ?? null,
|
|
1086
|
+
title: meetingTitle,
|
|
1087
|
+
time: formatTime(msg.created_at)
|
|
1088
|
+
}
|
|
1089
|
+
)
|
|
1090
|
+
] }, msg.external_id);
|
|
1108
1091
|
}
|
|
1109
|
-
|
|
1092
|
+
if (msg.kind === "call" && msg.call_ext_id && !deleted) {
|
|
1093
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Fragment, { children: [
|
|
1094
|
+
separator,
|
|
1095
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1096
|
+
ChatCallCard,
|
|
1097
|
+
{
|
|
1098
|
+
callExtId: msg.call_ext_id,
|
|
1099
|
+
senderName: msg.sender_ext_id ? senderName(msg.sender_ext_id) : null,
|
|
1100
|
+
latest: latestCallCards.has(msg.external_id),
|
|
1101
|
+
name: senderName,
|
|
1102
|
+
time: formatTime(msg.created_at)
|
|
1103
|
+
}
|
|
1104
|
+
)
|
|
1105
|
+
] }, msg.external_id);
|
|
1106
|
+
}
|
|
1107
|
+
return renderItem(item, i);
|
|
1108
|
+
}),
|
|
1109
|
+
view === "all" && /* @__PURE__ */ jsxRuntime.jsx(ProvisionalSpeakers, { ids: provisionalSpeakers })
|
|
1110
1110
|
] });
|
|
1111
1111
|
}
|
|
1112
1112
|
|
|
@@ -1131,5 +1131,5 @@ exports.matchesQuery = matchesQuery;
|
|
|
1131
1131
|
exports.useCallPersonName = useCallPersonName;
|
|
1132
1132
|
exports.useMeetingThreadMessages = useMeetingThreadMessages;
|
|
1133
1133
|
exports.useProvisionalSpeakers = useProvisionalSpeakers;
|
|
1134
|
-
//# sourceMappingURL=chunk-
|
|
1135
|
-
//# sourceMappingURL=chunk-
|
|
1134
|
+
//# sourceMappingURL=chunk-IHJ7BEI5.cjs.map
|
|
1135
|
+
//# sourceMappingURL=chunk-IHJ7BEI5.cjs.map
|