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