@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,98 +1,22 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var chunk5HEMXXHR_cjs = require('./chunk-5HEMXXHR.cjs');
|
|
5
5
|
var chunkBFKTZUFT_cjs = require('./chunk-BFKTZUFT.cjs');
|
|
6
6
|
var chunkWV65MJ43_cjs = require('./chunk-WV65MJ43.cjs');
|
|
7
7
|
var chunkZT5MIFLC_cjs = require('./chunk-ZT5MIFLC.cjs');
|
|
8
8
|
var chunkUIXY4HKM_cjs = require('./chunk-UIXY4HKM.cjs');
|
|
9
|
-
var react = require('@arbidocs/react');
|
|
10
|
-
var react
|
|
9
|
+
var react$1 = require('@arbidocs/react');
|
|
10
|
+
var react = require('react');
|
|
11
11
|
var lucideReact = require('lucide-react');
|
|
12
12
|
var ui = require('@arbidocs/react/ui');
|
|
13
13
|
var jsxRuntime = require('react/jsx-runtime');
|
|
14
14
|
var core = require('@arbidocs/react/document-tools/core');
|
|
15
15
|
|
|
16
|
-
function joinNames(people, name) {
|
|
17
|
-
const names = people.map(name);
|
|
18
|
-
return names.length > 4 ? `${names.slice(0, 4).join(", ")} +${names.length - 4}` : names.join(", ");
|
|
19
|
-
}
|
|
20
|
-
function ThreadCallLogCard({
|
|
21
|
-
detail,
|
|
22
|
-
name,
|
|
23
|
-
workspaceExtId,
|
|
24
|
-
time
|
|
25
|
-
}) {
|
|
26
|
-
const arbi = react.useArbi();
|
|
27
|
-
const openCallMeetingChat = react.useOpenCallMeetingChat();
|
|
28
|
-
const live = !detail.ended_at;
|
|
29
|
-
const inThisCall = react.useCallSession((s) => s.active?.callExtId === detail.call_ext_id);
|
|
30
|
-
const inAnotherCall = react.useCallSession(
|
|
31
|
-
(s) => !!s.active && s.active.callExtId !== detail.call_ext_id
|
|
32
|
-
);
|
|
33
|
-
const { data: call } = react.useCall(live ? detail.call_ext_id : null);
|
|
34
|
-
const invitedOnly = live && !!call && !call.my_sealed_key;
|
|
35
|
-
const [busy, setBusy] = react$1.useState(false);
|
|
36
|
-
const summary = live ? [
|
|
37
|
-
detail.started_by ? `Call started by ${name(detail.started_by)}` : "Call started",
|
|
38
|
-
detail.invited.length ? `invited ${joinNames(detail.invited, name)}` : null
|
|
39
|
-
] : [
|
|
40
|
-
"Call",
|
|
41
|
-
chunkUAF2J7P7_cjs.formatCallDuration(detail.duration_s),
|
|
42
|
-
detail.joined.length ? `joined ${joinNames(detail.joined, name)}` : null
|
|
43
|
-
];
|
|
44
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
45
|
-
"div",
|
|
46
|
-
{
|
|
47
|
-
className: "mx-auto my-1 flex w-fit max-w-full flex-wrap items-center justify-center gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs",
|
|
48
|
-
"data-testid": "thread-call-log-card",
|
|
49
|
-
"data-live": live || void 0,
|
|
50
|
-
children: [
|
|
51
|
-
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 }),
|
|
52
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-testid": "thread-call-log-summary", children: summary.filter(Boolean).join(" \xB7 ") }),
|
|
53
|
-
time && /* @__PURE__ */ jsxRuntime.jsx("time", { className: "text-muted-foreground", children: time }),
|
|
54
|
-
live ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
55
|
-
ui.Button,
|
|
56
|
-
{
|
|
57
|
-
type: "button",
|
|
58
|
-
size: "sm",
|
|
59
|
-
className: "h-7 bg-green-600 text-white hover:bg-green-700",
|
|
60
|
-
disabled: busy || inThisCall || inAnotherCall || invitedOnly,
|
|
61
|
-
title: invitedOnly ? "Only the people rung into this call can join" : inAnotherCall ? "You are already in a call" : void 0,
|
|
62
|
-
onClick: () => {
|
|
63
|
-
setBusy(true);
|
|
64
|
-
void react.openCall(arbi, { callExtId: detail.call_ext_id }).finally(() => setBusy(false));
|
|
65
|
-
},
|
|
66
|
-
"data-testid": "thread-call-log-join",
|
|
67
|
-
children: inThisCall ? "In call" : "Join"
|
|
68
|
-
}
|
|
69
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
70
|
-
ui.Button,
|
|
71
|
-
{
|
|
72
|
-
type: "button",
|
|
73
|
-
size: "sm",
|
|
74
|
-
variant: "outline",
|
|
75
|
-
className: "h-7",
|
|
76
|
-
onClick: () => void openCallMeetingChat({
|
|
77
|
-
callExtId: detail.call_ext_id,
|
|
78
|
-
meetingConversationExtId: detail.meeting_conversation_ext_id,
|
|
79
|
-
workspaceExtId
|
|
80
|
-
}),
|
|
81
|
-
"data-testid": "thread-call-log-open-chat",
|
|
82
|
-
children: [
|
|
83
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "mr-1 size-3.5", "aria-hidden": true }),
|
|
84
|
-
"Open meeting chat"
|
|
85
|
-
]
|
|
86
|
-
}
|
|
87
|
-
)
|
|
88
|
-
]
|
|
89
|
-
}
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
16
|
var NEW_THREAD = "__new__";
|
|
93
17
|
function useCurrentWorkspace() {
|
|
94
18
|
const { workspaceId, userId } = chunkWV65MJ43_cjs.useConnectedWorkspace();
|
|
95
|
-
const { data: workspaces } = react.useWorkspaces();
|
|
19
|
+
const { data: workspaces } = react$1.useWorkspaces();
|
|
96
20
|
const workspace = workspaces?.find((w) => w.external_id === workspaceId);
|
|
97
21
|
const role = workspace?.users?.find((wu) => wu.user.external_id === userId)?.role ?? null;
|
|
98
22
|
return { workspace, role };
|
|
@@ -104,11 +28,11 @@ function SaveTranscriptToThread({
|
|
|
104
28
|
iconOnly = false,
|
|
105
29
|
className
|
|
106
30
|
}) {
|
|
107
|
-
const [open, setOpen] = react
|
|
31
|
+
const [open, setOpen] = react.useState(false);
|
|
108
32
|
if (!lines.length) return null;
|
|
109
33
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
110
34
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
111
|
-
|
|
35
|
+
chunk5HEMXXHR_cjs.HeaderAction,
|
|
112
36
|
{
|
|
113
37
|
label: "Save transcript to thread",
|
|
114
38
|
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "size-3.5", "aria-hidden": true }),
|
|
@@ -136,7 +60,7 @@ function SaveTranscriptDialog({
|
|
|
136
60
|
onClose
|
|
137
61
|
}) {
|
|
138
62
|
const { notify } = chunkUIXY4HKM_cjs.useBlocksEnvironment();
|
|
139
|
-
const save = react.useSaveToThread();
|
|
63
|
+
const save = react$1.useSaveToThread();
|
|
140
64
|
const { workspace } = useCurrentWorkspace();
|
|
141
65
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
142
66
|
PickThreadDialog,
|
|
@@ -175,12 +99,12 @@ function PickThreadDialog({
|
|
|
175
99
|
const { role } = useCurrentWorkspace();
|
|
176
100
|
const { data: conversations } = chunkBFKTZUFT_cjs.useConnectedConversations();
|
|
177
101
|
const canPost = role === "owner" || role === "collaborator";
|
|
178
|
-
const threads = react
|
|
102
|
+
const threads = react.useMemo(
|
|
179
103
|
() => canPost ? conversations.filter((c) => c.is_shared && c.external_id !== excludeConversationExtId).sort((a, b) => Date.parse(b.updated_at) - Date.parse(a.updated_at)) : [],
|
|
180
104
|
[conversations, canPost, excludeConversationExtId]
|
|
181
105
|
);
|
|
182
|
-
const [target, setTarget] = react
|
|
183
|
-
const [busy, setBusy] = react
|
|
106
|
+
const [target, setTarget] = react.useState(NEW_THREAD);
|
|
107
|
+
const [busy, setBusy] = react.useState(false);
|
|
184
108
|
const save = async () => {
|
|
185
109
|
setBusy(true);
|
|
186
110
|
try {
|
|
@@ -232,9 +156,9 @@ function RecordingCard({
|
|
|
232
156
|
title,
|
|
233
157
|
time
|
|
234
158
|
}) {
|
|
235
|
-
const { data: call } = react.useCall(callExtId);
|
|
236
|
-
const one = react.useCallRecording(callExtId, recordingExtId);
|
|
237
|
-
const all = react.useCallRecordings(callExtId, !recordingExtId);
|
|
159
|
+
const { data: call } = react$1.useCall(callExtId);
|
|
160
|
+
const one = react$1.useCallRecording(callExtId, recordingExtId);
|
|
161
|
+
const all = react$1.useCallRecordings(callExtId, !recordingExtId);
|
|
238
162
|
if (!call) return null;
|
|
239
163
|
if (recordingExtId) {
|
|
240
164
|
if (one.isError) return /* @__PURE__ */ jsxRuntime.jsx(RecordingUnavailable, {});
|
|
@@ -256,9 +180,9 @@ function RecordingsList({
|
|
|
256
180
|
title,
|
|
257
181
|
className
|
|
258
182
|
}) {
|
|
259
|
-
const { data: call } = react.useCall(callExtId);
|
|
260
|
-
const { data, isLoading, isError } = react.useCallRecordings(callExtId);
|
|
261
|
-
const sorted = react
|
|
183
|
+
const { data: call } = react$1.useCall(callExtId);
|
|
184
|
+
const { data, isLoading, isError } = react$1.useCallRecordings(callExtId);
|
|
185
|
+
const sorted = react.useMemo(
|
|
262
186
|
() => [...data ?? []].sort((a, b) => Date.parse(b.started_at) - Date.parse(a.started_at)),
|
|
263
187
|
[data]
|
|
264
188
|
);
|
|
@@ -287,9 +211,9 @@ function ConfirmButton({
|
|
|
287
211
|
onConfirm,
|
|
288
212
|
icon
|
|
289
213
|
}) {
|
|
290
|
-
const [asking, setAsking] = react
|
|
291
|
-
const [busy, setBusy] = react
|
|
292
|
-
react
|
|
214
|
+
const [asking, setAsking] = react.useState(false);
|
|
215
|
+
const [busy, setBusy] = react.useState(false);
|
|
216
|
+
react.useEffect(() => {
|
|
293
217
|
if (!asking) return;
|
|
294
218
|
const t = setTimeout(() => setAsking(false), 5e3);
|
|
295
219
|
return () => clearTimeout(t);
|
|
@@ -325,33 +249,33 @@ function RecordingCardBody({
|
|
|
325
249
|
title,
|
|
326
250
|
time
|
|
327
251
|
}) {
|
|
328
|
-
const arbi = react.useArbi();
|
|
329
|
-
const actions = react.useRecordingActions(call);
|
|
330
|
-
const save = react.useSaveToThread();
|
|
252
|
+
const arbi = react$1.useArbi();
|
|
253
|
+
const actions = react$1.useRecordingActions(call);
|
|
254
|
+
const save = react$1.useSaveToThread();
|
|
331
255
|
const { notify, runtimeConfig } = chunkUIXY4HKM_cjs.useBlocksEnvironment();
|
|
332
256
|
const isHost = call.is_creator;
|
|
333
257
|
const mediaDeleted = !!recording.media_deleted_at;
|
|
334
258
|
const live = recording.state === "recording" || !recording.stopped_at && !mediaDeleted;
|
|
335
|
-
const speakers = react.speakerTracks(recording);
|
|
336
|
-
const timeline = react
|
|
337
|
-
const durationMs = react.timelineDurationMs(timeline);
|
|
259
|
+
const speakers = react$1.speakerTracks(recording);
|
|
260
|
+
const timeline = react.useMemo(() => react$1.timelineOf(recording.tracks ?? []), [recording.tracks]);
|
|
261
|
+
const durationMs = react$1.timelineDurationMs(timeline);
|
|
338
262
|
const hasMedia = !mediaDeleted && timeline.length > 0;
|
|
339
|
-
const [opened, setOpened] = react
|
|
340
|
-
const [playing, setPlaying] = react
|
|
341
|
-
const [progress, setProgress] = react
|
|
342
|
-
const [saveOpen, setSaveOpen] = react
|
|
263
|
+
const [opened, setOpened] = react.useState(null);
|
|
264
|
+
const [playing, setPlaying] = react.useState(false);
|
|
265
|
+
const [progress, setProgress] = react.useState(null);
|
|
266
|
+
const [saveOpen, setSaveOpen] = react.useState(false);
|
|
343
267
|
const { workspaceId: selectedWorkspaceId } = chunkWV65MJ43_cjs.useConnectedWorkspace();
|
|
344
268
|
const pending = chunkZT5MIFLC_cjs.usePendingRecording();
|
|
345
269
|
const highlighted = pending === recording.external_id;
|
|
346
|
-
const cardRef = react
|
|
347
|
-
react
|
|
270
|
+
const cardRef = react.useRef(null);
|
|
271
|
+
react.useEffect(() => {
|
|
348
272
|
if (!highlighted) return;
|
|
349
273
|
cardRef.current?.scrollIntoView({ block: "center", behavior: "smooth" });
|
|
350
274
|
const t = setTimeout(() => chunkZT5MIFLC_cjs.setPendingRecording(null), 4e3);
|
|
351
275
|
return () => clearTimeout(t);
|
|
352
276
|
}, [highlighted]);
|
|
353
277
|
const { refresh } = actions;
|
|
354
|
-
const open = react
|
|
278
|
+
const open = react.useCallback(async () => {
|
|
355
279
|
if (opened && opened.recording === recording) return opened;
|
|
356
280
|
const next = await actions.open(recording);
|
|
357
281
|
setOpened(next);
|
|
@@ -369,7 +293,7 @@ function RecordingCardBody({
|
|
|
369
293
|
}
|
|
370
294
|
};
|
|
371
295
|
const download = () => run("Decrypting\u2026", async () => {
|
|
372
|
-
const files = await react.recordingFiles(
|
|
296
|
+
const files = await react$1.recordingFiles(
|
|
373
297
|
arbi,
|
|
374
298
|
await open(),
|
|
375
299
|
title,
|
|
@@ -389,7 +313,7 @@ function RecordingCardBody({
|
|
|
389
313
|
);
|
|
390
314
|
});
|
|
391
315
|
const copyLink = async () => {
|
|
392
|
-
const ref = react.meetingChatRefFrom(call);
|
|
316
|
+
const ref = react$1.meetingChatRefFrom(call);
|
|
393
317
|
if (!ref) {
|
|
394
318
|
notify("This recording has no meeting chat to link to", "error");
|
|
395
319
|
return;
|
|
@@ -405,7 +329,7 @@ function RecordingCardBody({
|
|
|
405
329
|
};
|
|
406
330
|
const saveToThread = async (target) => {
|
|
407
331
|
if (!selectedWorkspaceId) throw new Error("Open a workspace first");
|
|
408
|
-
const files = await react.recordingFiles(
|
|
332
|
+
const files = await react$1.recordingFiles(
|
|
409
333
|
arbi,
|
|
410
334
|
await open(),
|
|
411
335
|
title,
|
|
@@ -427,8 +351,8 @@ function RecordingCardBody({
|
|
|
427
351
|
};
|
|
428
352
|
const summary = [
|
|
429
353
|
"Recording",
|
|
430
|
-
|
|
431
|
-
|
|
354
|
+
chunk5HEMXXHR_cjs.MODE_LABEL[recording.mode],
|
|
355
|
+
chunk5HEMXXHR_cjs.formatCallDuration(durationMs / 1e3),
|
|
432
356
|
speakers.length ? `${speakers.length} ${speakers.length === 1 ? "speaker" : "speakers"}` : null
|
|
433
357
|
].filter(Boolean).join(" \xB7 ");
|
|
434
358
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -455,7 +379,7 @@ function RecordingCardBody({
|
|
|
455
379
|
] }),
|
|
456
380
|
speakers.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "flex flex-wrap items-center gap-1 text-muted-foreground", children: speakers.map(
|
|
457
381
|
(t, i) => t.speaker_ext_id ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
458
|
-
|
|
382
|
+
chunk5HEMXXHR_cjs.CallUserPill,
|
|
459
383
|
{
|
|
460
384
|
identity: t.speaker_ext_id,
|
|
461
385
|
name: t.speaker_name
|
|
@@ -588,14 +512,14 @@ function RecordingCardBody({
|
|
|
588
512
|
"select",
|
|
589
513
|
{
|
|
590
514
|
className: "h-7 rounded-sm border border-border bg-background px-1 text-xs text-foreground",
|
|
591
|
-
value:
|
|
515
|
+
value: chunk5HEMXXHR_cjs.expiryChoiceOf(recording.expires_at ?? null),
|
|
592
516
|
onChange: (e) => {
|
|
593
517
|
const days = e.target.value === "none" ? null : Number(e.target.value);
|
|
594
|
-
void arbi.calls.recording.setExpiry(call.external_id, recording.external_id,
|
|
518
|
+
void arbi.calls.recording.setExpiry(call.external_id, recording.external_id, chunk5HEMXXHR_cjs.expiryFor(days)).then(refresh).catch((err) => notify(err.message, "error"));
|
|
595
519
|
},
|
|
596
520
|
"data-testid": "recording-expiry",
|
|
597
521
|
"aria-label": "Keep the audio and video for",
|
|
598
|
-
children:
|
|
522
|
+
children: chunk5HEMXXHR_cjs.EXPIRY_DAYS.map((d) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: d ?? "none", children: d ? `${d} days` : "until deleted" }, d ?? "none"))
|
|
599
523
|
}
|
|
600
524
|
)
|
|
601
525
|
] }),
|
|
@@ -626,8 +550,8 @@ function RecordingPlayer({
|
|
|
626
550
|
open,
|
|
627
551
|
durationMs
|
|
628
552
|
}) {
|
|
629
|
-
const composite = react.compositeTrack(recording);
|
|
630
|
-
const [view, setView] = react
|
|
553
|
+
const composite = react$1.compositeTrack(recording);
|
|
554
|
+
const [view, setView] = react.useState(composite?.parts?.length ? "video" : "audio");
|
|
631
555
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", "data-testid": "recording-player", children: [
|
|
632
556
|
composite?.parts?.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-1", role: "group", "aria-label": "Play", children: ["video", "audio"].map((v) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
633
557
|
"button",
|
|
@@ -650,10 +574,10 @@ function CompositeVideo({
|
|
|
650
574
|
open,
|
|
651
575
|
trackExtId
|
|
652
576
|
}) {
|
|
653
|
-
const arbi = react.useArbi();
|
|
654
|
-
const [urls, setUrls] = react
|
|
655
|
-
const [error, setError] = react
|
|
656
|
-
react
|
|
577
|
+
const arbi = react$1.useArbi();
|
|
578
|
+
const [urls, setUrls] = react.useState(null);
|
|
579
|
+
const [error, setError] = react.useState(null);
|
|
580
|
+
react.useEffect(() => {
|
|
657
581
|
let cancelled = false;
|
|
658
582
|
let made = [];
|
|
659
583
|
void (async () => {
|
|
@@ -662,7 +586,7 @@ function CompositeVideo({
|
|
|
662
586
|
const track = (opened.recording.tracks ?? []).find((t) => t.external_id === trackExtId);
|
|
663
587
|
const key = opened.keys.get(trackExtId);
|
|
664
588
|
if (!track || !key) throw new Error("The video does not open with your key");
|
|
665
|
-
const blobs = await react.compositeFiles(arbi, track, key);
|
|
589
|
+
const blobs = await react$1.compositeFiles(arbi, track, key);
|
|
666
590
|
made = blobs.map((b) => URL.createObjectURL(b));
|
|
667
591
|
if (cancelled) made.forEach((u) => URL.revokeObjectURL(u));
|
|
668
592
|
else setUrls(made);
|
|
@@ -705,21 +629,21 @@ function MixPlayer({
|
|
|
705
629
|
open,
|
|
706
630
|
durationMs
|
|
707
631
|
}) {
|
|
708
|
-
const arbi = react.useArbi();
|
|
632
|
+
const arbi = react$1.useArbi();
|
|
709
633
|
const { notify } = chunkUIXY4HKM_cjs.useBlocksEnvironment();
|
|
710
|
-
const parts = react
|
|
711
|
-
const [position, setPosition] = react
|
|
712
|
-
const [playing, setPlaying] = react
|
|
713
|
-
const session = react
|
|
714
|
-
const halt = react
|
|
634
|
+
const parts = react.useMemo(() => react$1.timelineOf(react$1.speakerTracks(recording)), [recording]);
|
|
635
|
+
const [position, setPosition] = react.useState(0);
|
|
636
|
+
const [playing, setPlaying] = react.useState(false);
|
|
637
|
+
const session = react.useRef(null);
|
|
638
|
+
const halt = react.useCallback(() => {
|
|
715
639
|
const s = session.current;
|
|
716
640
|
session.current = null;
|
|
717
641
|
if (!s) return;
|
|
718
642
|
clearInterval(s.timer);
|
|
719
643
|
void s.ctx.close().catch(() => void 0);
|
|
720
644
|
}, []);
|
|
721
|
-
react
|
|
722
|
-
const play = react
|
|
645
|
+
react.useEffect(() => halt, [halt]);
|
|
646
|
+
const play = react.useCallback(
|
|
723
647
|
async (fromMs) => {
|
|
724
648
|
halt();
|
|
725
649
|
const opened = await open();
|
|
@@ -737,10 +661,10 @@ function MixPlayer({
|
|
|
737
661
|
const raw = track?.parts?.find((p) => p.seq === part.seq);
|
|
738
662
|
if (!track || !key || !raw) return;
|
|
739
663
|
try {
|
|
740
|
-
const bytes = await react.fetchPart(arbi, raw, key);
|
|
741
|
-
const buffer = await ctx.decodeAudioData(react.standalone(bytes).buffer);
|
|
664
|
+
const bytes = await react$1.fetchPart(arbi, raw, key);
|
|
665
|
+
const buffer = await ctx.decodeAudioData(react$1.standalone(bytes).buffer);
|
|
742
666
|
if (session.current !== s) return;
|
|
743
|
-
const at = react.schedulePart({
|
|
667
|
+
const at = react$1.schedulePart({
|
|
744
668
|
partOffsetMs: part.offsetMs,
|
|
745
669
|
bufferDurationS: buffer.duration,
|
|
746
670
|
ctxStart: s.ctxStart,
|
|
@@ -758,15 +682,15 @@ function MixPlayer({
|
|
|
758
682
|
};
|
|
759
683
|
const tick = () => {
|
|
760
684
|
if (session.current !== s) return;
|
|
761
|
-
const head = react.playheadAt(ctx.currentTime, s.ctxStart, s.seekMs);
|
|
685
|
+
const head = react$1.playheadAt(ctx.currentTime, s.ctxStart, s.seekMs);
|
|
762
686
|
setPosition(Math.min(head, durationMs));
|
|
763
687
|
if (head >= durationMs) {
|
|
764
688
|
halt();
|
|
765
689
|
setPlaying(false);
|
|
766
690
|
return;
|
|
767
691
|
}
|
|
768
|
-
for (const part of react.partsDue(parts, head, react.PLAYBACK_LOOKAHEAD_MS, s.scheduled)) {
|
|
769
|
-
s.scheduled.add(react.partKey(part));
|
|
692
|
+
for (const part of react$1.partsDue(parts, head, react$1.PLAYBACK_LOOKAHEAD_MS, s.scheduled)) {
|
|
693
|
+
s.scheduled.add(react$1.partKey(part));
|
|
770
694
|
void schedule(part);
|
|
771
695
|
}
|
|
772
696
|
};
|
|
@@ -828,11 +752,87 @@ function MixPlayer({
|
|
|
828
752
|
] })
|
|
829
753
|
] });
|
|
830
754
|
}
|
|
755
|
+
function joinNames(people, name) {
|
|
756
|
+
const names = people.map(name);
|
|
757
|
+
return names.length > 4 ? `${names.slice(0, 4).join(", ")} +${names.length - 4}` : names.join(", ");
|
|
758
|
+
}
|
|
759
|
+
function ThreadCallLogCard({
|
|
760
|
+
detail,
|
|
761
|
+
name,
|
|
762
|
+
workspaceExtId,
|
|
763
|
+
time
|
|
764
|
+
}) {
|
|
765
|
+
const arbi = react$1.useArbi();
|
|
766
|
+
const openCallMeetingChat = react$1.useOpenCallMeetingChat();
|
|
767
|
+
const live = !detail.ended_at;
|
|
768
|
+
const inThisCall = react$1.useCallSession((s) => s.active?.callExtId === detail.call_ext_id);
|
|
769
|
+
const inAnotherCall = react$1.useCallSession(
|
|
770
|
+
(s) => !!s.active && s.active.callExtId !== detail.call_ext_id
|
|
771
|
+
);
|
|
772
|
+
const { data: call } = react$1.useCall(live ? detail.call_ext_id : null);
|
|
773
|
+
const invitedOnly = live && !!call && !call.my_sealed_key;
|
|
774
|
+
const [busy, setBusy] = react.useState(false);
|
|
775
|
+
const summary = live ? [
|
|
776
|
+
detail.started_by ? `Call started by ${name(detail.started_by)}` : "Call started",
|
|
777
|
+
detail.invited.length ? `invited ${joinNames(detail.invited, name)}` : null
|
|
778
|
+
] : [
|
|
779
|
+
"Call",
|
|
780
|
+
chunk5HEMXXHR_cjs.formatCallDuration(detail.duration_s),
|
|
781
|
+
detail.joined.length ? `joined ${joinNames(detail.joined, name)}` : null
|
|
782
|
+
];
|
|
783
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
784
|
+
"div",
|
|
785
|
+
{
|
|
786
|
+
className: "mx-auto my-1 flex w-fit max-w-full flex-wrap items-center justify-center gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs",
|
|
787
|
+
"data-testid": "thread-call-log-card",
|
|
788
|
+
"data-live": live || void 0,
|
|
789
|
+
children: [
|
|
790
|
+
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 }),
|
|
791
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-testid": "thread-call-log-summary", children: summary.filter(Boolean).join(" \xB7 ") }),
|
|
792
|
+
time && /* @__PURE__ */ jsxRuntime.jsx("time", { className: "text-muted-foreground", children: time }),
|
|
793
|
+
live ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
794
|
+
ui.Button,
|
|
795
|
+
{
|
|
796
|
+
type: "button",
|
|
797
|
+
size: "sm",
|
|
798
|
+
className: "h-7 bg-green-600 text-white hover:bg-green-700",
|
|
799
|
+
disabled: busy || inThisCall || inAnotherCall || invitedOnly,
|
|
800
|
+
title: invitedOnly ? "Only the people rung into this call can join" : inAnotherCall ? "You are already in a call" : void 0,
|
|
801
|
+
onClick: () => {
|
|
802
|
+
setBusy(true);
|
|
803
|
+
void react$1.openCall(arbi, { callExtId: detail.call_ext_id }).finally(() => setBusy(false));
|
|
804
|
+
},
|
|
805
|
+
"data-testid": "thread-call-log-join",
|
|
806
|
+
children: inThisCall ? "In call" : "Join"
|
|
807
|
+
}
|
|
808
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
809
|
+
ui.Button,
|
|
810
|
+
{
|
|
811
|
+
type: "button",
|
|
812
|
+
size: "sm",
|
|
813
|
+
variant: "outline",
|
|
814
|
+
className: "h-7",
|
|
815
|
+
onClick: () => void openCallMeetingChat({
|
|
816
|
+
callExtId: detail.call_ext_id,
|
|
817
|
+
meetingConversationExtId: detail.meeting_conversation_ext_id,
|
|
818
|
+
workspaceExtId
|
|
819
|
+
}),
|
|
820
|
+
"data-testid": "thread-call-log-open-chat",
|
|
821
|
+
children: [
|
|
822
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "mr-1 size-3.5", "aria-hidden": true }),
|
|
823
|
+
"Open meeting chat"
|
|
824
|
+
]
|
|
825
|
+
}
|
|
826
|
+
)
|
|
827
|
+
]
|
|
828
|
+
}
|
|
829
|
+
);
|
|
830
|
+
}
|
|
831
831
|
|
|
832
832
|
exports.PickThreadDialog = PickThreadDialog;
|
|
833
833
|
exports.RecordingCard = RecordingCard;
|
|
834
834
|
exports.RecordingsList = RecordingsList;
|
|
835
835
|
exports.SaveTranscriptToThread = SaveTranscriptToThread;
|
|
836
836
|
exports.ThreadCallLogCard = ThreadCallLogCard;
|
|
837
|
-
//# sourceMappingURL=chunk-
|
|
838
|
-
//# sourceMappingURL=chunk-
|
|
837
|
+
//# sourceMappingURL=chunk-F5T4W2R2.cjs.map
|
|
838
|
+
//# sourceMappingURL=chunk-F5T4W2R2.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/calls/connected/SaveTranscriptToThread.tsx","../src/calls/connected/RecordingCard.tsx","../src/calls/connected/ThreadCallLogCard.tsx"],"names":["useConnectedWorkspace","useWorkspaces","useState","jsxs","Fragment","jsx","HeaderAction","FileText","useBlocksEnvironment","useSaveToThread","useConnectedConversations","useMemo","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","cn","DialogFooter","Button","useCall","useCallRecording","useCallRecordings","Loader2","useEffect","useArbi","useRecordingActions","speakerTracks","timelineOf","timelineDurationMs","usePendingRecording","useRef","setPendingRecording","useCallback","recordingFiles","downloadBlob","meetingChatRefFrom","recordingLink","MODE_LABEL","formatCallDuration","Video","Mic","CallUserPill","Pause","Play","Download","Link2","Captions","FileUp","Trash2","expiryChoiceOf","expiryFor","compositeTrack","compositeFiles","fetchPart","standalone","schedulePart","playheadAt","partsDue","PLAYBACK_LOOKAHEAD_MS","partKey","useOpenCallMeetingChat","useCallSession","Phone","PhoneOff","openCall","MessageSquare"],"mappings":"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","file":"chunk-F5T4W2R2.cjs","sourcesContent":["/**\n * Host action \"Save transcript to thread\": the meeting chat's transcript is decrypted here, in the\n * host's browser, and posted as ONE attributed transcript comment (title, date, then\n * `Speaker [hh:mm:ss]: text` lines) into a workspace thread the host picks — a shared thread of the\n * current workspace they can post in, or a new one. The thread is encrypted with the workspace key\n * like any comment; the meeting chat itself is unchanged and nobody outside it gains access to it.\n */\n\nimport { useSaveToThread, useWorkspaces, type TranscriptExportLine } from '@arbidocs/react'\nimport { useMemo, useState, type ReactElement, type ReactNode } from 'react'\nimport { FileText } from 'lucide-react'\nimport {\n Button,\n cn,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@arbidocs/react/ui'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { useConnectedWorkspace } from '../../connection/ConnectionProvider'\nimport { useConnectedConversations } from '../../connection/workspaceData'\nimport { HeaderAction } from '../HeaderAction'\n\nconst NEW_THREAD = '__new__'\n\n/** The open workspace and my role in it (the threads I can post in are its shared ones). */\nfunction useCurrentWorkspace() {\n const { workspaceId, userId } = useConnectedWorkspace()\n const { data: workspaces } = useWorkspaces()\n const workspace = workspaces?.find((w) => w.external_id === workspaceId)\n const role = workspace?.users?.find((wu) => wu.user.external_id === userId)?.role ?? null\n return { workspace, role }\n}\n\nexport function SaveTranscriptToThread({\n title,\n lines,\n excludeConversationExtId,\n iconOnly = false,\n className,\n}: {\n /** The meeting's title (decrypted). */\n title: string | null | undefined\n lines: TranscriptExportLine[]\n /** Not offered as a target (the meeting thread itself). */\n excludeConversationExtId?: string | null\n /** Icon only, the label in a tooltip (a crowded header). */\n iconOnly?: boolean\n className?: string\n}): ReactElement | null {\n const [open, setOpen] = useState(false)\n if (!lines.length) return null\n return (\n <>\n <HeaderAction\n label=\"Save transcript to thread\"\n icon={<FileText className=\"size-3.5\" aria-hidden />}\n iconOnly={iconOnly}\n className={className}\n onClick={() => setOpen(true)}\n testId=\"save-transcript-to-thread\"\n />\n {open && (\n <SaveTranscriptDialog\n title={title}\n lines={lines}\n excludeConversationExtId={excludeConversationExtId ?? null}\n onClose={() => setOpen(false)}\n />\n )}\n </>\n )\n}\n\nfunction SaveTranscriptDialog({\n title,\n lines,\n excludeConversationExtId,\n onClose,\n}: {\n title: string | null | undefined\n lines: TranscriptExportLine[]\n excludeConversationExtId: string | null\n onClose(): void\n}): ReactElement {\n const { notify } = useBlocksEnvironment()\n const save = useSaveToThread()\n const { workspace } = useCurrentWorkspace()\n return (\n <PickThreadDialog\n heading=\"Save transcript to thread\"\n description={\n <>\n The transcript ({lines.length} {lines.length === 1 ? 'line' : 'lines'}) is posted as one\n comment in a thread of {workspace?.name ?? 'the current workspace'}. Only that thread’s\n members can read it there.\n </>\n }\n testIdPrefix=\"save-transcript\"\n excludeConversationExtId={excludeConversationExtId}\n onClose={onClose}\n onConfirm={async (target) => {\n await save.transcript({ conversationExtId: target, title, lines })\n notify('Transcript saved to the thread', 'success')\n }}\n />\n )\n}\n\n/**\n * Pick a shared thread of the current workspace I can post in (or a new one) and act on it: the\n * dialog behind \"Save transcript to thread\" and the recording's \"Save to thread\".\n */\nexport function PickThreadDialog({\n heading,\n description,\n testIdPrefix,\n excludeConversationExtId,\n confirmLabel = 'Save',\n busyLabel = 'Saving…',\n onConfirm,\n onClose,\n}: {\n heading: string\n description: ReactNode\n /** `<prefix>-dialog`, `<prefix>-target-<id>`, `<prefix>-confirm`. */\n testIdPrefix: string\n excludeConversationExtId?: string | null\n confirmLabel?: string\n busyLabel?: string\n /** `target` null: a new thread. Throwing keeps the dialog open and shows the error. */\n onConfirm(target: string | null): Promise<unknown>\n onClose(): void\n}): ReactElement {\n const { notify } = useBlocksEnvironment()\n const { role } = useCurrentWorkspace()\n const { data: conversations } = useConnectedConversations()\n const canPost = role === 'owner' || role === 'collaborator'\n const threads = useMemo(\n () =>\n canPost\n ? conversations\n .filter((c) => c.is_shared && c.external_id !== excludeConversationExtId)\n .sort((a, b) => Date.parse(b.updated_at) - Date.parse(a.updated_at))\n : [],\n [conversations, canPost, excludeConversationExtId]\n )\n const [target, setTarget] = useState<string>(NEW_THREAD)\n const [busy, setBusy] = useState(false)\n\n const save = async () => {\n setBusy(true)\n try {\n await onConfirm(target === NEW_THREAD ? null : target)\n onClose()\n } catch (err) {\n notify((err as Error).message, 'error')\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <Dialog open onOpenChange={(o) => !o && !busy && onClose()}>\n <DialogContent className=\"sm:max-w-md\" data-testid={`${testIdPrefix}-dialog`}>\n <DialogHeader>\n <DialogTitle>{heading}</DialogTitle>\n <DialogDescription>{description}</DialogDescription>\n </DialogHeader>\n {!canPost ? (\n <p className=\"text-sm text-muted-foreground\">\n Open a workspace you can post in to save here.\n </p>\n ) : (\n <ul className=\"flex max-h-72 flex-col gap-1 overflow-y-auto\" role=\"radiogroup\">\n {[{ external_id: NEW_THREAD, title: 'New thread' }, ...threads].map((t) => (\n <li key={t.external_id}>\n <button\n type=\"button\"\n role=\"radio\"\n aria-checked={target === t.external_id}\n className={cn(\n 'w-full truncate rounded-md px-2 py-1.5 text-left text-sm hover:bg-muted',\n target === t.external_id && 'bg-muted font-medium'\n )}\n onClick={() => setTarget(t.external_id)}\n data-testid={`${testIdPrefix}-target-${t.external_id}`}\n >\n {t.title || 'Untitled thread'}\n </button>\n </li>\n ))}\n </ul>\n )}\n <DialogFooter>\n <Button variant=\"ghost\" onClick={onClose} disabled={busy}>\n Cancel\n </Button>\n <Button\n onClick={() => void save()}\n disabled={busy || !canPost}\n data-testid={`${testIdPrefix}-confirm`}\n >\n {busy ? busyLabel : confirmLabel}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","/**\n * The Recording card of a call (ARBI `docs/meeting-chats-plan.md` §6): a `kind = recording` chat\n * message in an E2E meeting chat, a `recording` activity event in a workspace meeting thread, and\n * each entry of a meeting chat's \"Recordings\" list.\n *\n * Everything that touches media happens in this browser: parts are downloaded as ciphertext and\n * decrypted with the track keys (unwrapped under the meeting chat's / workspace's key). Members of\n * the meeting chat can play, download and copy an in-app link; the host can also transcribe, delete\n * the media (keeping the transcript), set an expiry, save the files to a thread, or delete it.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactElement } from 'react'\nimport {\n Captions,\n Download,\n FileUp,\n Link2,\n Loader2,\n Mic,\n Pause,\n Play,\n Trash2,\n Video,\n} from 'lucide-react'\nimport { Button, cn } from '@arbidocs/react/ui'\nimport { downloadBlob } from '@arbidocs/react/document-tools/core'\nimport {\n useArbi,\n useCallRecording,\n useCallRecordings,\n useCall,\n useRecordingActions,\n useSaveToThread,\n meetingChatRefFrom,\n compositeFiles,\n compositeTrack,\n fetchPart,\n recordingFiles,\n speakerTracks,\n type OpenedRecording,\n PLAYBACK_LOOKAHEAD_MS,\n partKey,\n partsDue,\n playheadAt,\n schedulePart,\n standalone,\n timelineDurationMs,\n timelineOf,\n type TimelinePart,\n} from '@arbidocs/react'\nimport type { calls } from '@arbidocs/sdk/browser'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { useConnectedWorkspace } from '../../connection/ConnectionProvider'\nimport { recordingLink, setPendingRecording, usePendingRecording } from '../recording-link'\nimport { formatCallDuration } from '../call-cards'\nimport { EXPIRY_DAYS, MODE_LABEL, expiryChoiceOf, expiryFor } from '../recording-labels'\nimport { PickThreadDialog } from './SaveTranscriptToThread'\nimport { CallUserPill } from './CallUserPill'\n\n/** A card for one recording (by id), or for each of the call's recordings when no id is known. */\nexport function RecordingCard({\n callExtId,\n recordingExtId,\n title,\n time,\n}: {\n callExtId: string\n recordingExtId?: string | null\n /** The meeting's title (decrypted), for file names. */\n title?: string | null\n time?: string\n}): ReactElement | null {\n const { data: call } = useCall(callExtId)\n const one = useCallRecording(callExtId, recordingExtId)\n const all = useCallRecordings(callExtId, !recordingExtId)\n if (!call) return null\n if (recordingExtId) {\n if (one.isError) return <RecordingUnavailable />\n return one.data ? (\n <RecordingCardBody call={call} recording={one.data} title={title} time={time} />\n ) : null\n }\n return (\n <>\n {(all.data ?? []).map((r) => (\n <RecordingCardBody\n key={r.external_id}\n call={call}\n recording={r}\n title={title}\n time={time}\n />\n ))}\n </>\n )\n}\n\n/** All of a call's recordings (the meeting chat's \"Recordings\" view), newest first. */\nexport function RecordingsList({\n callExtId,\n title,\n className,\n}: {\n callExtId: string\n title?: string | null\n className?: string\n}): ReactElement {\n const { data: call } = useCall(callExtId)\n const { data, isLoading, isError } = useCallRecordings(callExtId)\n const sorted = useMemo(\n () => [...(data ?? [])].sort((a, b) => Date.parse(b.started_at) - Date.parse(a.started_at)),\n [data]\n )\n return (\n <div className={cn('flex flex-col gap-2', className)} data-testid=\"recordings-list\">\n {isLoading && <Loader2 className=\"mx-auto size-4 animate-spin text-muted-foreground\" />}\n {isError && (\n <p className=\"text-center text-xs text-muted-foreground\">Could not load the recordings.</p>\n )}\n {!isLoading && !isError && !sorted.length && (\n <p className=\"text-center text-xs text-muted-foreground\">No recordings yet.</p>\n )}\n {call &&\n sorted.map((r) => (\n <RecordingCardBody key={r.external_id} call={call} recording={r} title={title} />\n ))}\n </div>\n )\n}\n\nfunction RecordingUnavailable(): ReactElement {\n return (\n <div\n className=\"mx-auto my-1 w-fit rounded-md border border-border bg-card px-3 py-2 text-xs text-muted-foreground\"\n data-testid=\"recording-card\"\n >\n Recording unavailable\n </div>\n )\n}\n\n/** A two-step destructive button: the first click asks, the second does. */\nfunction ConfirmButton({\n label,\n confirmLabel,\n testId,\n disabled,\n onConfirm,\n icon,\n}: {\n label: string\n confirmLabel: string\n testId: string\n disabled?: boolean\n onConfirm(): Promise<void>\n icon: ReactElement\n}): ReactElement {\n const [asking, setAsking] = useState(false)\n const [busy, setBusy] = useState(false)\n useEffect(() => {\n if (!asking) return\n const t = setTimeout(() => setAsking(false), 5000)\n return () => clearTimeout(t)\n }, [asking])\n return (\n <Button\n type=\"button\"\n size=\"sm\"\n variant={asking ? 'destructive' : 'outline'}\n className=\"h-7\"\n disabled={disabled || busy}\n onClick={() => {\n if (!asking) {\n setAsking(true)\n return\n }\n setAsking(false)\n setBusy(true)\n void onConfirm().finally(() => setBusy(false))\n }}\n data-testid={asking ? `${testId}-confirm` : testId}\n >\n {busy ? <Loader2 className=\"mr-1 size-3.5 animate-spin\" aria-hidden /> : icon}\n {asking ? confirmLabel : label}\n </Button>\n )\n}\n\nfunction RecordingCardBody({\n call,\n recording,\n title,\n time,\n}: {\n call: calls.CallResponse\n recording: calls.CallRecording\n title?: string | null\n time?: string\n}): ReactElement {\n const arbi = useArbi()\n const actions = useRecordingActions(call)\n const save = useSaveToThread()\n const { notify, runtimeConfig } = useBlocksEnvironment()\n const isHost = call.is_creator\n const mediaDeleted = !!recording.media_deleted_at\n const live = recording.state === 'recording' || (!recording.stopped_at && !mediaDeleted)\n const speakers = speakerTracks(recording)\n const timeline = useMemo(() => timelineOf(recording.tracks ?? []), [recording.tracks])\n const durationMs = timelineDurationMs(timeline)\n const hasMedia = !mediaDeleted && timeline.length > 0\n const [opened, setOpened] = useState<OpenedRecording | null>(null)\n const [playing, setPlaying] = useState(false)\n const [progress, setProgress] = useState<string | null>(null)\n const [saveOpen, setSaveOpen] = useState(false)\n const { workspaceId: selectedWorkspaceId } = useConnectedWorkspace()\n\n // A link asked to show this recording: bring it into view.\n const pending = usePendingRecording()\n const highlighted = pending === recording.external_id\n const cardRef = useRef<HTMLDivElement | null>(null)\n useEffect(() => {\n if (!highlighted) return\n cardRef.current?.scrollIntoView({ block: 'center', behavior: 'smooth' })\n const t = setTimeout(() => setPendingRecording(null), 4000)\n return () => clearTimeout(t)\n }, [highlighted])\n\n const { refresh } = actions\n\n const open = useCallback(async (): Promise<OpenedRecording> => {\n if (opened && opened.recording === recording) return opened\n const next = await actions.open(recording)\n setOpened(next)\n return next\n }, [actions, opened, recording])\n\n const run = async (label: string, task: () => Promise<void>) => {\n setProgress(label)\n try {\n await task()\n } catch (err) {\n console.warn('[calls] recording action failed', err)\n notify((err as Error).message, 'error')\n } finally {\n setProgress(null)\n }\n }\n\n const download = () =>\n run('Decrypting…', async () => {\n const files = await recordingFiles(arbi, await open(), title, (done, total) =>\n setProgress(`Decrypting ${done}/${total}…`)\n )\n if (!files.length) throw new Error('Nothing to download')\n for (const f of files) downloadBlob(f, f.name)\n })\n\n const transcribe = () =>\n run('Transcribing…', async () => {\n const { stored, failed } = await actions.transcribe(await open(), (done, total) =>\n setProgress(`Transcribing ${done}/${total}…`)\n )\n notify(\n failed\n ? `Transcribed ${stored} lines; ${failed} parts failed`\n : `Transcribed ${stored} lines into the meeting chat`,\n failed ? 'warning' : 'success'\n )\n })\n\n const copyLink = async () => {\n const ref = meetingChatRefFrom(call)\n if (!ref) {\n notify('This recording has no meeting chat to link to', 'error')\n return\n }\n try {\n await navigator.clipboard.writeText(\n recordingLink(ref, recording.external_id, runtimeConfig.deploymentDomain)\n )\n notify('Link copied: it opens for members of the meeting chat', 'success')\n } catch {\n notify('Could not copy the link', 'error')\n }\n }\n\n const saveToThread = async (target: string | null) => {\n if (!selectedWorkspaceId) throw new Error('Open a workspace first')\n const files = await recordingFiles(arbi, await open(), title, (done, total) =>\n setProgress(`Decrypting ${done}/${total}…`)\n )\n if (!files.length) throw new Error('Nothing to save')\n // Re-encrypted under the workspace key, as a direct document upload.\n try {\n await save.recording({\n workspaceExtId: selectedWorkspaceId,\n files,\n conversationExtId: target,\n title,\n onUploading: () => setProgress('Uploading…'),\n })\n } finally {\n setProgress(null)\n }\n notify('Recording saved to the thread', 'success')\n }\n\n const summary = [\n 'Recording',\n MODE_LABEL[recording.mode],\n formatCallDuration(durationMs / 1000),\n speakers.length ? `${speakers.length} ${speakers.length === 1 ? 'speaker' : 'speakers'}` : null,\n ]\n .filter(Boolean)\n .join(' · ')\n\n return (\n <div\n ref={cardRef}\n className={cn(\n 'mx-auto my-1 flex w-full max-w-xl flex-col gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs',\n highlighted && 'ring-2 ring-primary'\n )}\n data-testid=\"recording-card\"\n data-recording={recording.external_id}\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n {recording.mode === 'audio_video' ? (\n <Video className=\"size-4 text-red-500\" aria-hidden />\n ) : (\n <Mic className=\"size-4 text-red-500\" aria-hidden />\n )}\n <span className=\"font-medium\" data-testid=\"recording-summary\">\n {summary}\n </span>\n {time && <time className=\"text-muted-foreground\">{time}</time>}\n {live && <span className=\"text-red-500\">recording…</span>}\n {mediaDeleted && (\n <span className=\"text-muted-foreground\">Audio and video deleted — transcript kept</span>\n )}\n {!mediaDeleted && recording.expires_at && (\n <span className=\"text-muted-foreground\">\n Deleted after {new Date(recording.expires_at).toLocaleDateString()}\n </span>\n )}\n </div>\n {speakers.length > 0 && (\n <p className=\"flex flex-wrap items-center gap-1 text-muted-foreground\">\n {speakers.map((t, i) =>\n t.speaker_ext_id ? (\n <CallUserPill\n key={t.speaker_ext_id}\n identity={t.speaker_ext_id}\n name={t.speaker_name}\n />\n ) : (\n <span key={i}>{t.speaker_name || 'Someone'}</span>\n )\n )}\n </p>\n )}\n <div className=\"flex flex-wrap items-center gap-1.5\">\n {hasMedia && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n aria-pressed={playing}\n onClick={() => setPlaying((p) => !p)}\n data-testid=\"recording-play\"\n >\n {playing ? (\n <Pause className=\"mr-1 size-3.5\" aria-hidden />\n ) : (\n <Play className=\"mr-1 size-3.5\" aria-hidden />\n )}\n {playing ? 'Close player' : 'Play'}\n </Button>\n )}\n {hasMedia && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n disabled={!!progress}\n onClick={() => void download()}\n data-testid=\"recording-download\"\n >\n <Download className=\"mr-1 size-3.5\" aria-hidden />\n Download\n </Button>\n )}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n onClick={() => void copyLink()}\n title=\"Copy an in-app link (only members of the meeting chat can open it)\"\n data-testid=\"recording-copy-link\"\n >\n <Link2 className=\"mr-1 size-3.5\" aria-hidden />\n Copy link\n </Button>\n {isHost && hasMedia && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n disabled={!!progress || live}\n onClick={() => void transcribe()}\n data-testid=\"recording-transcribe\"\n >\n <Captions className=\"mr-1 size-3.5\" aria-hidden />\n Transcribe\n </Button>\n )}\n {isHost && hasMedia && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n disabled={!!progress || live}\n onClick={() => setSaveOpen(true)}\n data-testid=\"recording-save-to-thread\"\n >\n <FileUp className=\"mr-1 size-3.5\" aria-hidden />\n Save to thread\n </Button>\n )}\n {isHost && !mediaDeleted && (\n <ConfirmButton\n label=\"Keep transcript, delete audio/video\"\n confirmLabel=\"Delete audio/video now\"\n testId=\"recording-delete-media\"\n disabled={!!progress || live}\n icon={<Trash2 className=\"mr-1 size-3.5\" aria-hidden />}\n onConfirm={async () => {\n try {\n await arbi.calls.recording.deleteMedia(call.external_id, recording.external_id)\n setPlaying(false)\n setOpened(null)\n refresh()\n } catch (err) {\n notify((err as Error).message, 'error')\n }\n }}\n />\n )}\n {isHost && (\n <ConfirmButton\n label=\"Delete\"\n confirmLabel=\"Delete recording\"\n testId=\"recording-delete\"\n disabled={!!progress || live}\n icon={<Trash2 className=\"mr-1 size-3.5\" aria-hidden />}\n onConfirm={async () => {\n try {\n await arbi.calls.recording.delete(call.external_id, recording.external_id)\n refresh()\n } catch (err) {\n notify((err as Error).message, 'error')\n }\n }}\n />\n )}\n {isHost && !mediaDeleted && (\n <label className=\"flex items-center gap-1 text-muted-foreground\">\n Keep\n <select\n className=\"h-7 rounded-sm border border-border bg-background px-1 text-xs text-foreground\"\n value={expiryChoiceOf(recording.expires_at ?? null)}\n onChange={(e) => {\n const days = e.target.value === 'none' ? null : Number(e.target.value)\n void arbi.calls.recording\n .setExpiry(call.external_id, recording.external_id, expiryFor(days))\n .then(refresh)\n .catch((err: unknown) => notify((err as Error).message, 'error'))\n }}\n data-testid=\"recording-expiry\"\n aria-label=\"Keep the audio and video for\"\n >\n {EXPIRY_DAYS.map((d) => (\n <option key={d ?? 'none'} value={d ?? 'none'}>\n {d ? `${d} days` : 'until deleted'}\n </option>\n ))}\n </select>\n </label>\n )}\n {progress && (\n <span className=\"inline-flex items-center gap-1 text-muted-foreground\">\n <Loader2 className=\"size-3.5 animate-spin\" aria-hidden />\n {progress}\n </span>\n )}\n </div>\n {playing && hasMedia && (\n <RecordingPlayer recording={recording} open={open} durationMs={durationMs} />\n )}\n {saveOpen && (\n <PickThreadDialog\n heading=\"Save recording to thread\"\n description=\"The recording is decrypted here and uploaded as documents (one audio file per speaker, and the video) into a thread of the current workspace, encrypted under its key. Only that workspace’s members can read them there.\"\n testIdPrefix=\"save-recording\"\n confirmLabel=\"Save\"\n busyLabel=\"Saving…\"\n onClose={() => setSaveOpen(false)}\n onConfirm={saveToThread}\n />\n )}\n </div>\n )\n}\n\n/**\n * Plays a recording: the composite video when there is one (it carries the mixed audio the host\n * heard), otherwise the speaker tracks mixed in sync on one WebAudio timeline.\n */\nfunction RecordingPlayer({\n recording,\n open,\n durationMs,\n}: {\n recording: calls.CallRecording\n open(): Promise<OpenedRecording>\n durationMs: number\n}): ReactElement {\n const composite = compositeTrack(recording)\n const [view, setView] = useState<'video' | 'audio'>(composite?.parts?.length ? 'video' : 'audio')\n return (\n <div className=\"flex flex-col gap-2\" data-testid=\"recording-player\">\n {composite?.parts?.length ? (\n <div className=\"flex gap-1\" role=\"group\" aria-label=\"Play\">\n {(['video', 'audio'] as const).map((v) => (\n <button\n key={v}\n type=\"button\"\n className={cn(\n 'rounded-full px-2 py-0.5',\n view === v ? 'bg-muted font-medium' : 'text-muted-foreground hover:bg-muted'\n )}\n aria-pressed={view === v}\n onClick={() => setView(v)}\n >\n {v === 'video' ? 'Video' : 'Speakers'}\n </button>\n ))}\n </div>\n ) : null}\n {view === 'video' && composite ? (\n <CompositeVideo open={open} trackExtId={composite.external_id} />\n ) : (\n <MixPlayer recording={recording} open={open} durationMs={durationMs} />\n )}\n </div>\n )\n}\n\nfunction CompositeVideo({\n open,\n trackExtId,\n}: {\n open(): Promise<OpenedRecording>\n trackExtId: string\n}): ReactElement {\n const arbi = useArbi()\n const [urls, setUrls] = useState<string[] | null>(null)\n const [error, setError] = useState<string | null>(null)\n useEffect(() => {\n let cancelled = false\n let made: string[] = []\n void (async () => {\n try {\n const opened = await open()\n const track = (opened.recording.tracks ?? []).find((t) => t.external_id === trackExtId)\n const key = opened.keys.get(trackExtId)\n if (!track || !key) throw new Error('The video does not open with your key')\n const blobs = await compositeFiles(arbi, track, key)\n made = blobs.map((b) => URL.createObjectURL(b))\n if (cancelled) made.forEach((u) => URL.revokeObjectURL(u))\n else setUrls(made)\n } catch (err) {\n if (!cancelled) setError((err as Error).message)\n }\n })()\n return () => {\n cancelled = true\n made.forEach((u) => URL.revokeObjectURL(u))\n }\n }, [arbi, open, trackExtId])\n if (error) return <p className=\"text-destructive\">{error}</p>\n if (!urls) {\n return (\n <span className=\"inline-flex items-center gap-1 text-muted-foreground\">\n <Loader2 className=\"size-3.5 animate-spin\" aria-hidden />\n Decrypting the video…\n </span>\n )\n }\n return (\n <>\n {urls.map((u, i) => (\n <video\n key={u}\n src={u}\n controls\n className=\"w-full rounded-sm bg-black\"\n aria-label={`Video ${i + 1}`}\n />\n ))}\n </>\n )\n}\n\nconst fmt = (ms: number) => {\n const s = Math.max(0, Math.floor(ms / 1000))\n const h = Math.floor(s / 3600)\n const m = Math.floor((s % 3600) / 60)\n const sec = String(s % 60).padStart(2, '0')\n return h ? `${h}:${String(m).padStart(2, '0')}:${sec}` : `${m}:${sec}`\n}\n\n/**\n * The speaker tracks mixed in sync: parts are fetched, decrypted and decoded a little ahead of the\n * playhead and started on one AudioContext clock at their offsets (see `recording-playback.ts`).\n */\nfunction MixPlayer({\n recording,\n open,\n durationMs,\n}: {\n recording: calls.CallRecording\n open(): Promise<OpenedRecording>\n durationMs: number\n}): ReactElement {\n const arbi = useArbi()\n const { notify } = useBlocksEnvironment()\n const parts = useMemo(() => timelineOf(speakerTracks(recording)), [recording])\n const [position, setPosition] = useState(0)\n const [playing, setPlaying] = useState(false)\n const session = useRef<{\n ctx: AudioContext\n ctxStart: number\n seekMs: number\n scheduled: Set<string>\n timer: ReturnType<typeof setInterval>\n } | null>(null)\n\n const halt = useCallback(() => {\n const s = session.current\n session.current = null\n if (!s) return\n clearInterval(s.timer)\n void s.ctx.close().catch(() => undefined)\n }, [])\n\n useEffect(() => halt, [halt])\n\n const play = useCallback(\n async (fromMs: number) => {\n halt()\n const opened = await open()\n const ctx = new AudioContext()\n const s = {\n ctx,\n ctxStart: ctx.currentTime + 0.25,\n seekMs: fromMs,\n scheduled: new Set<string>(),\n timer: 0 as unknown as ReturnType<typeof setInterval>,\n }\n const schedule = async (part: TimelinePart) => {\n const track = (opened.recording.tracks ?? []).find((t) => t.external_id === part.trackExtId)\n const key = opened.keys.get(part.trackExtId)\n const raw = track?.parts?.find((p) => p.seq === part.seq)\n if (!track || !key || !raw) return\n try {\n const bytes = await fetchPart(arbi, raw, key)\n const buffer = await ctx.decodeAudioData(standalone(bytes).buffer)\n if (session.current !== s) return\n const at = schedulePart({\n partOffsetMs: part.offsetMs,\n bufferDurationS: buffer.duration,\n ctxStart: s.ctxStart,\n seekMs: s.seekMs,\n ctxNow: ctx.currentTime,\n })\n if (!at) return\n const source = ctx.createBufferSource()\n source.buffer = buffer\n source.connect(ctx.destination)\n source.start(at.when, at.offset)\n } catch (err) {\n console.warn('[calls] a recording part does not play', err)\n }\n }\n const tick = () => {\n if (session.current !== s) return\n const head = playheadAt(ctx.currentTime, s.ctxStart, s.seekMs)\n setPosition(Math.min(head, durationMs))\n if (head >= durationMs) {\n halt()\n setPlaying(false)\n return\n }\n for (const part of partsDue(parts, head, PLAYBACK_LOOKAHEAD_MS, s.scheduled)) {\n s.scheduled.add(partKey(part))\n void schedule(part)\n }\n }\n s.timer = setInterval(tick, 500)\n session.current = s\n setPlaying(true)\n tick()\n },\n [arbi, open, parts, durationMs, halt]\n )\n\n const toggle = () => {\n if (playing) {\n halt()\n setPlaying(false)\n } else {\n void play(position >= durationMs ? 0 : position).catch((err: unknown) => {\n setPlaying(false)\n notify((err as Error).message, 'error')\n })\n }\n }\n\n return (\n <div className=\"flex items-center gap-2\">\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"outline\"\n className=\"size-7\"\n aria-label={playing ? 'Pause' : 'Play'}\n onClick={toggle}\n data-testid=\"recording-mix-toggle\"\n >\n {playing ? <Pause className=\"size-3.5\" /> : <Play className=\"size-3.5\" />}\n </Button>\n <input\n type=\"range\"\n min={0}\n max={Math.max(1, durationMs)}\n step={1000}\n value={position}\n className=\"flex-1\"\n aria-label=\"Position\"\n onChange={(e) => {\n const ms = Number(e.target.value)\n setPosition(ms)\n if (playing) {\n void play(ms).catch((err: unknown) => notify((err as Error).message, 'error'))\n }\n }}\n />\n <span className=\"tabular-nums text-muted-foreground\">\n {fmt(position)} / {fmt(durationMs)}\n </span>\n </div>\n )\n}\n","/**\n * A thread call's log card in the thread transcript: the `convo_events` row of kind `call` the\n * server writes when the call starts and updates when it ends (plaintext ids and times only).\n *\n * live: \"Call started by Ada · invited Bob, Cy\" · Join\n * ended: \"Call · 12 min · joined Ada, Bob\" · Open meeting chat\n *\n * It re-reads on `call.started` / `call.ended` (see `refreshCallCards`).\n */\n\nimport { useArbi, useCallSession, useCall, useOpenCallMeetingChat, openCall } from '@arbidocs/react'\nimport { useState, type ReactElement } from 'react'\nimport { MessageSquare, Phone, PhoneOff } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\nimport { formatCallDuration, type CallLogDetail } from '../call-cards'\n\nfunction joinNames(people: string[], name: (id: string) => string): string {\n const names = people.map(name)\n return names.length > 4\n ? `${names.slice(0, 4).join(', ')} +${names.length - 4}`\n : names.join(', ')\n}\n\nexport function ThreadCallLogCard({\n detail,\n name,\n workspaceExtId,\n time,\n}: {\n detail: CallLogDetail\n /** A person's display name by user ext id. */\n name: (userExtId: string) => string\n /** The thread's workspace (the meeting thread lives there too). */\n workspaceExtId: string | null\n time?: string\n}): ReactElement {\n const arbi = useArbi()\n const openCallMeetingChat = useOpenCallMeetingChat()\n const live = !detail.ended_at\n const inThisCall = useCallSession((s) => s.active?.callExtId === detail.call_ext_id)\n const inAnotherCall = useCallSession(\n (s) => !!s.active && s.active.callExtId !== detail.call_ext_id\n )\n // Only people holding K (the creator and those rung) can join from the card.\n const { data: call } = useCall(live ? detail.call_ext_id : null)\n const invitedOnly = live && !!call && !call.my_sealed_key\n const [busy, setBusy] = useState(false)\n\n const summary = live\n ? [\n detail.started_by ? `Call started by ${name(detail.started_by)}` : 'Call started',\n detail.invited.length ? `invited ${joinNames(detail.invited, name)}` : null,\n ]\n : [\n 'Call',\n formatCallDuration(detail.duration_s),\n detail.joined.length ? `joined ${joinNames(detail.joined, name)}` : null,\n ]\n\n return (\n <div\n className=\"mx-auto my-1 flex w-fit max-w-full flex-wrap items-center justify-center gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs\"\n data-testid=\"thread-call-log-card\"\n data-live={live || undefined}\n >\n {live ? (\n <Phone className=\"size-4 animate-pulse text-green-text\" aria-hidden />\n ) : (\n <PhoneOff className=\"size-4 text-muted-foreground\" aria-hidden />\n )}\n <span data-testid=\"thread-call-log-summary\">{summary.filter(Boolean).join(' · ')}</span>\n {time && <time className=\"text-muted-foreground\">{time}</time>}\n {live ? (\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"h-7 bg-green-600 text-white hover:bg-green-700\"\n disabled={busy || inThisCall || inAnotherCall || invitedOnly}\n title={\n invitedOnly\n ? 'Only the people rung into this call can join'\n : inAnotherCall\n ? 'You are already in a call'\n : undefined\n }\n onClick={() => {\n setBusy(true)\n void openCall(arbi, { callExtId: detail.call_ext_id }).finally(() => setBusy(false))\n }}\n data-testid=\"thread-call-log-join\"\n >\n {inThisCall ? 'In call' : 'Join'}\n </Button>\n ) : (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n onClick={() =>\n void openCallMeetingChat({\n callExtId: detail.call_ext_id,\n meetingConversationExtId: detail.meeting_conversation_ext_id,\n workspaceExtId,\n })\n }\n data-testid=\"thread-call-log-open-chat\"\n >\n <MessageSquare className=\"mr-1 size-3.5\" aria-hidden />\n Open meeting chat\n </Button>\n )}\n </div>\n )\n}\n"]}
|