@dxos/plugin-thread 0.8.4-main.3eb6e50203 → 0.8.4-main.422d1c7879

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 (446) hide show
  1. package/dist/lib/browser/add-message-VPPFFLFL.mjs +97 -0
  2. package/dist/lib/browser/add-message-VPPFFLFL.mjs.map +7 -0
  3. package/dist/lib/browser/blueprints/index.mjs +33 -4
  4. package/dist/lib/browser/blueprints/index.mjs.map +4 -4
  5. package/dist/lib/browser/chunk-MESW3R4Q.mjs +61 -0
  6. package/dist/lib/browser/chunk-MESW3R4Q.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-VPM44Z35.mjs +259 -0
  8. package/dist/lib/browser/chunk-VPM44Z35.mjs.map +7 -0
  9. package/dist/lib/browser/create-UGT7V733.mjs +55 -0
  10. package/dist/lib/browser/create-UGT7V733.mjs.map +7 -0
  11. package/dist/lib/browser/create-channel-EF67LCS6.mjs +21 -0
  12. package/dist/lib/browser/create-channel-EF67LCS6.mjs.map +7 -0
  13. package/dist/lib/browser/create-channel-thread-CCZTSWQ6.mjs +28 -0
  14. package/dist/lib/browser/create-channel-thread-CCZTSWQ6.mjs.map +7 -0
  15. package/dist/lib/browser/create-proposals-CMK7S7VS.mjs +57 -0
  16. package/dist/lib/browser/create-proposals-CMK7S7VS.mjs.map +7 -0
  17. package/dist/lib/browser/delete-FSFVU6ZA.mjs +59 -0
  18. package/dist/lib/browser/delete-FSFVU6ZA.mjs.map +7 -0
  19. package/dist/lib/browser/delete-message-XL5M5J33.mjs +64 -0
  20. package/dist/lib/browser/delete-message-XL5M5J33.mjs.map +7 -0
  21. package/dist/lib/browser/index.mjs +2189 -176
  22. package/dist/lib/browser/index.mjs.map +4 -4
  23. package/dist/lib/browser/meta.json +1 -1
  24. package/dist/lib/browser/on-create-space-VYS2JGVT.mjs +25 -0
  25. package/dist/lib/browser/on-create-space-VYS2JGVT.mjs.map +7 -0
  26. package/dist/lib/browser/operations/index.mjs +14 -0
  27. package/dist/lib/browser/operations/index.mjs.map +7 -0
  28. package/dist/lib/browser/restore-2ZGMKUSD.mjs +33 -0
  29. package/dist/lib/browser/restore-2ZGMKUSD.mjs.map +7 -0
  30. package/dist/lib/browser/restore-message-OYEGWPII.mjs +42 -0
  31. package/dist/lib/browser/restore-message-OYEGWPII.mjs.map +7 -0
  32. package/dist/lib/browser/select-VG2XLULE.mjs +26 -0
  33. package/dist/lib/browser/select-VG2XLULE.mjs.map +7 -0
  34. package/dist/lib/browser/toggle-resolved-MM6YC5BU.mjs +45 -0
  35. package/dist/lib/browser/toggle-resolved-MM6YC5BU.mjs.map +7 -0
  36. package/dist/lib/browser/types/index.mjs +5 -7
  37. package/dist/lib/node-esm/add-message-XWKHLNS6.mjs +98 -0
  38. package/dist/lib/node-esm/add-message-XWKHLNS6.mjs.map +7 -0
  39. package/dist/lib/node-esm/blueprints/index.mjs +33 -4
  40. package/dist/lib/node-esm/blueprints/index.mjs.map +4 -4
  41. package/dist/lib/node-esm/chunk-JTHXNWKJ.mjs +260 -0
  42. package/dist/lib/node-esm/chunk-JTHXNWKJ.mjs.map +7 -0
  43. package/dist/lib/node-esm/chunk-SDRAQNSQ.mjs +62 -0
  44. package/dist/lib/node-esm/chunk-SDRAQNSQ.mjs.map +7 -0
  45. package/dist/lib/node-esm/create-XAYNDVU2.mjs +56 -0
  46. package/dist/lib/node-esm/create-XAYNDVU2.mjs.map +7 -0
  47. package/dist/lib/node-esm/create-channel-UYWUNB3L.mjs +22 -0
  48. package/dist/lib/node-esm/create-channel-UYWUNB3L.mjs.map +7 -0
  49. package/dist/lib/node-esm/create-channel-thread-UQF2SBHS.mjs +29 -0
  50. package/dist/lib/node-esm/create-channel-thread-UQF2SBHS.mjs.map +7 -0
  51. package/dist/lib/node-esm/create-proposals-5FJNURKH.mjs +58 -0
  52. package/dist/lib/node-esm/create-proposals-5FJNURKH.mjs.map +7 -0
  53. package/dist/lib/node-esm/delete-WRODXR3E.mjs +60 -0
  54. package/dist/lib/node-esm/delete-WRODXR3E.mjs.map +7 -0
  55. package/dist/lib/node-esm/delete-message-TAHCYTW2.mjs +65 -0
  56. package/dist/lib/node-esm/delete-message-TAHCYTW2.mjs.map +7 -0
  57. package/dist/lib/node-esm/index.mjs +2189 -176
  58. package/dist/lib/node-esm/index.mjs.map +4 -4
  59. package/dist/lib/node-esm/meta.json +1 -1
  60. package/dist/lib/node-esm/on-create-space-XDY2YXPV.mjs +26 -0
  61. package/dist/lib/node-esm/on-create-space-XDY2YXPV.mjs.map +7 -0
  62. package/dist/lib/node-esm/operations/index.mjs +15 -0
  63. package/dist/lib/node-esm/operations/index.mjs.map +7 -0
  64. package/dist/lib/node-esm/restore-T3QA7TSL.mjs +34 -0
  65. package/dist/lib/node-esm/restore-T3QA7TSL.mjs.map +7 -0
  66. package/dist/lib/node-esm/restore-message-WFTEVBEV.mjs +43 -0
  67. package/dist/lib/node-esm/restore-message-WFTEVBEV.mjs.map +7 -0
  68. package/dist/lib/node-esm/select-Q4UDWJJF.mjs +27 -0
  69. package/dist/lib/node-esm/select-Q4UDWJJF.mjs.map +7 -0
  70. package/dist/lib/node-esm/toggle-resolved-33XTAK2H.mjs +46 -0
  71. package/dist/lib/node-esm/toggle-resolved-33XTAK2H.mjs.map +7 -0
  72. package/dist/lib/node-esm/types/index.mjs +5 -7
  73. package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
  74. package/dist/types/src/blueprints/index.d.ts +1 -1
  75. package/dist/types/src/blueprints/index.d.ts.map +1 -1
  76. package/dist/types/src/blueprints/thread-blueprint.d.ts +3 -20
  77. package/dist/types/src/blueprints/thread-blueprint.d.ts.map +1 -1
  78. package/dist/types/src/calls/util/calls-service.d.ts.map +1 -1
  79. package/dist/types/src/calls-service.stories.d.ts +2 -2
  80. package/dist/types/src/calls-service.stories.d.ts.map +1 -1
  81. package/dist/types/src/capabilities/app-graph-builder.d.ts +6 -0
  82. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  83. package/dist/types/src/capabilities/blueprint-definition.d.ts +6 -0
  84. package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -0
  85. package/dist/types/src/capabilities/call-manager.d.ts +6 -0
  86. package/dist/types/src/capabilities/call-manager.d.ts.map +1 -0
  87. package/dist/types/src/capabilities/index.d.ts +15 -10
  88. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  89. package/dist/types/src/capabilities/markdown.d.ts +5 -0
  90. package/dist/types/src/capabilities/markdown.d.ts.map +1 -0
  91. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  92. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  93. package/dist/types/src/capabilities/{react-root/react-root.d.ts → react-root.d.ts} +1 -1
  94. package/dist/types/src/capabilities/react-root.d.ts.map +1 -0
  95. package/dist/types/src/capabilities/react-surface.d.ts +5 -0
  96. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  97. package/dist/types/src/capabilities/settings.d.ts +7 -0
  98. package/dist/types/src/capabilities/settings.d.ts.map +1 -0
  99. package/dist/types/src/capabilities/state.d.ts +7 -0
  100. package/dist/types/src/capabilities/state.d.ts.map +1 -0
  101. package/dist/types/src/capabilities/undo-mappings.d.ts +5 -0
  102. package/dist/types/src/capabilities/undo-mappings.d.ts.map +1 -0
  103. package/dist/types/src/components/Call/Toolbar.d.ts +1 -1
  104. package/dist/types/src/components/Call/Toolbar.d.ts.map +1 -1
  105. package/dist/types/src/components/CommentsPanel/CommentsPanel.d.ts +13 -0
  106. package/dist/types/src/components/CommentsPanel/CommentsPanel.d.ts.map +1 -0
  107. package/dist/types/src/components/CommentsPanel/CommentsPanel.stories.d.ts +160 -0
  108. package/dist/types/src/components/CommentsPanel/CommentsPanel.stories.d.ts.map +1 -0
  109. package/dist/types/src/components/{CommentsThreadContainer.d.ts → CommentsPanel/CommentsThread.d.ts} +3 -3
  110. package/dist/types/src/components/CommentsPanel/CommentsThread.d.ts.map +1 -0
  111. package/dist/types/src/components/CommentsPanel/index.d.ts +3 -0
  112. package/dist/types/src/components/CommentsPanel/index.d.ts.map +1 -0
  113. package/dist/types/src/components/Lobby/Lobby.d.ts.map +1 -1
  114. package/dist/types/src/components/Media/VideoObject.stories.d.ts.map +1 -1
  115. package/dist/types/src/components/MessagePanel/MessagePanel.d.ts +15 -0
  116. package/dist/types/src/components/MessagePanel/MessagePanel.d.ts.map +1 -0
  117. package/dist/types/src/components/MessagePanel/index.d.ts +2 -0
  118. package/dist/types/src/components/MessagePanel/index.d.ts.map +1 -0
  119. package/dist/types/src/components/Participant/Participant.d.ts.map +1 -1
  120. package/dist/types/src/components/Participant/ParticipantGrid.d.ts.map +1 -1
  121. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.d.ts.map +1 -1
  122. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts +142 -144
  123. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts.map +1 -1
  124. package/dist/types/src/components/ResponsiveGrid/{ResponsiveContainer.d.ts → ResponsivePanel.d.ts} +4 -4
  125. package/dist/types/src/components/ResponsiveGrid/ResponsivePanel.d.ts.map +1 -0
  126. package/dist/types/src/components/ResponsiveGrid/ResponsivePanel.stories.d.ts +164 -0
  127. package/dist/types/src/components/ResponsiveGrid/ResponsivePanel.stories.d.ts.map +1 -0
  128. package/dist/types/src/components/ResponsiveGrid/index.d.ts +1 -1
  129. package/dist/types/src/components/ResponsiveGrid/index.d.ts.map +1 -1
  130. package/dist/types/src/components/ThreadSettings/ThreadSettings.d.ts +6 -0
  131. package/dist/types/src/components/ThreadSettings/ThreadSettings.d.ts.map +1 -0
  132. package/dist/types/src/components/ThreadSettings/ThreadSettings.stories.d.ts +161 -0
  133. package/dist/types/src/components/ThreadSettings/ThreadSettings.stories.d.ts.map +1 -0
  134. package/dist/types/src/components/ThreadSettings/index.d.ts +2 -0
  135. package/dist/types/src/components/ThreadSettings/index.d.ts.map +1 -0
  136. package/dist/types/src/components/index.d.ts +4 -9
  137. package/dist/types/src/components/index.d.ts.map +1 -1
  138. package/dist/types/src/{components → containers/CallDebugPanel}/CallDebugPanel.d.ts +1 -1
  139. package/dist/types/src/containers/CallDebugPanel/CallDebugPanel.d.ts.map +1 -0
  140. package/dist/types/src/containers/CallDebugPanel/index.d.ts +2 -0
  141. package/dist/types/src/containers/CallDebugPanel/index.d.ts.map +1 -0
  142. package/dist/types/src/{components → containers/CallSidebar}/CallSidebar.d.ts +0 -1
  143. package/dist/types/src/containers/CallSidebar/CallSidebar.d.ts.map +1 -0
  144. package/dist/types/src/containers/CallSidebar/index.d.ts +2 -0
  145. package/dist/types/src/containers/CallSidebar/index.d.ts.map +1 -0
  146. package/dist/types/src/containers/ChannelContainer/ChannelContainer.d.ts +12 -0
  147. package/dist/types/src/containers/ChannelContainer/ChannelContainer.d.ts.map +1 -0
  148. package/dist/types/src/containers/ChannelContainer/ChannelContainer.stories.d.ts +162 -0
  149. package/dist/types/src/containers/ChannelContainer/ChannelContainer.stories.d.ts.map +1 -0
  150. package/dist/types/src/containers/ChannelContainer/index.d.ts +2 -0
  151. package/dist/types/src/containers/ChannelContainer/index.d.ts.map +1 -0
  152. package/dist/types/src/{components → containers/ChatContainer}/ChatContainer.d.ts +3 -5
  153. package/dist/types/src/containers/ChatContainer/ChatContainer.d.ts.map +1 -0
  154. package/dist/types/src/containers/ChatContainer/ChatContainer.stories.d.ts +162 -0
  155. package/dist/types/src/containers/ChatContainer/ChatContainer.stories.d.ts.map +1 -0
  156. package/dist/types/src/containers/ChatContainer/index.d.ts +4 -0
  157. package/dist/types/src/containers/ChatContainer/index.d.ts.map +1 -0
  158. package/dist/types/src/containers/ThreadCompanion/ThreadCompanion.d.ts +8 -0
  159. package/dist/types/src/containers/ThreadCompanion/ThreadCompanion.d.ts.map +1 -0
  160. package/dist/types/src/containers/ThreadCompanion/index.d.ts +2 -0
  161. package/dist/types/src/containers/ThreadCompanion/index.d.ts.map +1 -0
  162. package/dist/types/src/containers/index.d.ts +7 -0
  163. package/dist/types/src/containers/index.d.ts.map +1 -0
  164. package/dist/types/src/{components/command-extension.d.ts → extensions/command.d.ts} +1 -1
  165. package/dist/types/src/extensions/command.d.ts.map +1 -0
  166. package/dist/types/src/extensions/index.d.ts +1 -0
  167. package/dist/types/src/extensions/index.d.ts.map +1 -1
  168. package/dist/types/src/extensions/threads.d.ts +1 -1
  169. package/dist/types/src/extensions/threads.d.ts.map +1 -1
  170. package/dist/types/src/hooks/analytics.d.ts.map +1 -1
  171. package/dist/types/src/operations/add-message.d.ts +5 -0
  172. package/dist/types/src/operations/add-message.d.ts.map +1 -0
  173. package/dist/types/src/operations/create-channel-thread.d.ts +5 -0
  174. package/dist/types/src/operations/create-channel-thread.d.ts.map +1 -0
  175. package/dist/types/src/operations/create-channel.d.ts +5 -0
  176. package/dist/types/src/operations/create-channel.d.ts.map +1 -0
  177. package/dist/types/src/operations/create-proposals.d.ts +5 -0
  178. package/dist/types/src/operations/create-proposals.d.ts.map +1 -0
  179. package/dist/types/src/operations/create.d.ts +5 -0
  180. package/dist/types/src/operations/create.d.ts.map +1 -0
  181. package/dist/types/src/operations/definitions.d.ts +2804 -0
  182. package/dist/types/src/operations/definitions.d.ts.map +1 -0
  183. package/dist/types/src/operations/delete-message.d.ts +5 -0
  184. package/dist/types/src/operations/delete-message.d.ts.map +1 -0
  185. package/dist/types/src/operations/delete.d.ts +5 -0
  186. package/dist/types/src/operations/delete.d.ts.map +1 -0
  187. package/dist/types/src/operations/index.d.ts +4 -0
  188. package/dist/types/src/operations/index.d.ts.map +1 -0
  189. package/dist/types/src/operations/on-create-space.d.ts +5 -0
  190. package/dist/types/src/operations/on-create-space.d.ts.map +1 -0
  191. package/dist/types/src/operations/restore-message.d.ts +5 -0
  192. package/dist/types/src/operations/restore-message.d.ts.map +1 -0
  193. package/dist/types/src/operations/restore.d.ts +5 -0
  194. package/dist/types/src/operations/restore.d.ts.map +1 -0
  195. package/dist/types/src/operations/select.d.ts +5 -0
  196. package/dist/types/src/operations/select.d.ts.map +1 -0
  197. package/dist/types/src/operations/toggle-resolved.d.ts +5 -0
  198. package/dist/types/src/operations/toggle-resolved.d.ts.map +1 -0
  199. package/dist/types/src/{components/testing.d.ts → testing/data.d.ts} +1 -1
  200. package/dist/types/src/testing/data.d.ts.map +1 -0
  201. package/dist/types/src/testing/stories.d.ts.map +1 -1
  202. package/dist/types/src/translations.d.ts +140 -142
  203. package/dist/types/src/translations.d.ts.map +1 -1
  204. package/dist/types/src/types/Channel.d.ts +37 -17
  205. package/dist/types/src/types/Channel.d.ts.map +1 -1
  206. package/dist/types/src/types/Settings.d.ts +5 -0
  207. package/dist/types/src/types/Settings.d.ts.map +1 -0
  208. package/dist/types/src/types/capabilities.d.ts +2 -1
  209. package/dist/types/src/types/capabilities.d.ts.map +1 -1
  210. package/dist/types/src/types/types.d.ts +1 -3227
  211. package/dist/types/src/types/types.d.ts.map +1 -1
  212. package/dist/types/src/util.d.ts.map +1 -1
  213. package/dist/types/tsconfig.tsbuildinfo +1 -1
  214. package/package.json +77 -70
  215. package/src/ThreadPlugin.tsx +28 -31
  216. package/src/blueprints/index.ts +1 -1
  217. package/src/blueprints/thread-blueprint.ts +13 -8
  218. package/src/calls/util/calls-service.ts +0 -1
  219. package/src/calls-service.stories.tsx +9 -8
  220. package/src/capabilities/{app-graph-builder/app-graph-builder.ts → app-graph-builder.ts} +39 -48
  221. package/src/capabilities/blueprint-definition.ts +17 -0
  222. package/src/capabilities/{call-manager/call-manager.ts → call-manager.ts} +4 -3
  223. package/src/capabilities/index.ts +16 -10
  224. package/src/capabilities/{markdown/markdown.ts → markdown.ts} +10 -11
  225. package/src/capabilities/operation-handler.ts +16 -0
  226. package/src/capabilities/{react-root/react-root.tsx → react-root.tsx} +2 -2
  227. package/src/capabilities/{react-surface/react-surface.tsx → react-surface.tsx} +28 -35
  228. package/src/capabilities/{settings/settings.ts → settings.ts} +6 -5
  229. package/src/capabilities/{state/state.ts → state.ts} +1 -1
  230. package/src/capabilities/undo-mappings.ts +46 -0
  231. package/src/components/Call/Call.tsx +4 -4
  232. package/src/components/Call/Toolbar.tsx +28 -20
  233. package/src/components/{Comments.stories.tsx → CommentsPanel/CommentsPanel.stories.tsx} +15 -15
  234. package/src/components/{CommentsContainer.tsx → CommentsPanel/CommentsPanel.tsx} +15 -14
  235. package/src/components/{CommentsThreadContainer.tsx → CommentsPanel/CommentsThread.tsx} +19 -20
  236. package/src/components/CommentsPanel/index.ts +6 -0
  237. package/src/components/Lobby/Lobby.tsx +7 -6
  238. package/src/components/Media/VideoObject.stories.tsx +6 -7
  239. package/src/components/Media/VideoObject.tsx +1 -1
  240. package/src/components/{MessageContainer.tsx → MessagePanel/MessagePanel.tsx} +23 -17
  241. package/src/components/MessagePanel/index.ts +5 -0
  242. package/src/components/Participant/Participant.tsx +2 -1
  243. package/src/components/Participant/ParticipantGrid.tsx +0 -1
  244. package/src/components/ResponsiveGrid/ResponsiveGrid.stories.tsx +10 -11
  245. package/src/components/ResponsiveGrid/ResponsiveGrid.tsx +8 -8
  246. package/src/components/ResponsiveGrid/ResponsiveGridItem.tsx +9 -9
  247. package/src/components/ResponsiveGrid/{ResponsiveContainer.stories.tsx → ResponsivePanel.stories.tsx} +7 -8
  248. package/src/components/ResponsiveGrid/{ResponsiveContainer.tsx → ResponsivePanel.tsx} +5 -5
  249. package/src/components/ResponsiveGrid/index.ts +1 -1
  250. package/src/components/ThreadSettings/ThreadSettings.stories.tsx +31 -0
  251. package/src/components/ThreadSettings/ThreadSettings.tsx +20 -0
  252. package/src/components/ThreadSettings/index.ts +5 -0
  253. package/src/components/index.ts +5 -9
  254. package/src/{components → containers/CallDebugPanel}/CallDebugPanel.tsx +8 -7
  255. package/src/containers/CallDebugPanel/index.ts +5 -0
  256. package/src/{components → containers/CallSidebar}/CallSidebar.tsx +3 -5
  257. package/src/containers/CallSidebar/index.ts +5 -0
  258. package/src/{components → containers/ChannelContainer}/ChannelContainer.stories.tsx +10 -9
  259. package/src/{components → containers/ChannelContainer}/ChannelContainer.tsx +73 -58
  260. package/src/containers/ChannelContainer/index.ts +5 -0
  261. package/src/{components/Chat.stories.tsx → containers/ChatContainer/ChatContainer.stories.tsx} +19 -18
  262. package/src/containers/ChatContainer/ChatContainer.tsx +131 -0
  263. package/src/containers/ChatContainer/index.ts +8 -0
  264. package/src/{components → containers/ThreadCompanion}/ThreadCompanion.tsx +69 -46
  265. package/src/containers/ThreadCompanion/index.ts +5 -0
  266. package/src/containers/index.ts +11 -0
  267. package/src/{components/command-extension.ts → extensions/command.ts} +1 -1
  268. package/src/extensions/index.ts +1 -0
  269. package/src/extensions/threads.ts +14 -13
  270. package/src/hooks/analytics.ts +2 -1
  271. package/src/meta.ts +2 -2
  272. package/src/operations/add-message.ts +81 -0
  273. package/src/operations/create-channel-thread.ts +26 -0
  274. package/src/operations/create-channel.ts +20 -0
  275. package/src/operations/create-proposals.ts +49 -0
  276. package/src/operations/create.ts +48 -0
  277. package/src/operations/definitions.ts +177 -0
  278. package/src/operations/delete-message.ts +53 -0
  279. package/src/operations/delete.ts +63 -0
  280. package/src/operations/index.ts +22 -0
  281. package/src/operations/on-create-space.ts +27 -0
  282. package/src/operations/restore-message.ts +38 -0
  283. package/src/operations/restore.ts +38 -0
  284. package/src/operations/select.ts +24 -0
  285. package/src/operations/toggle-resolved.ts +41 -0
  286. package/src/{components/testing.ts → testing/data.ts} +7 -7
  287. package/src/testing/stories.ts +7 -12
  288. package/src/translations.ts +72 -76
  289. package/src/types/Channel.ts +11 -4
  290. package/src/types/Settings.ts +10 -0
  291. package/src/types/capabilities.ts +9 -7
  292. package/src/types/types.ts +2 -184
  293. package/src/util.ts +1 -1
  294. package/dist/lib/browser/app-graph-builder-XFGLMIGK.mjs +0 -189
  295. package/dist/lib/browser/app-graph-builder-XFGLMIGK.mjs.map +0 -7
  296. package/dist/lib/browser/blueprint-definition-ACPH22F7.mjs +0 -18
  297. package/dist/lib/browser/blueprint-definition-ACPH22F7.mjs.map +0 -7
  298. package/dist/lib/browser/call-manager-GDGIKJKN.mjs +0 -26
  299. package/dist/lib/browser/call-manager-GDGIKJKN.mjs.map +0 -7
  300. package/dist/lib/browser/chunk-2FIHSX35.mjs +0 -293
  301. package/dist/lib/browser/chunk-2FIHSX35.mjs.map +0 -7
  302. package/dist/lib/browser/chunk-4EUEMHNI.mjs +0 -1817
  303. package/dist/lib/browser/chunk-4EUEMHNI.mjs.map +0 -7
  304. package/dist/lib/browser/chunk-CP7E2HRE.mjs +0 -31
  305. package/dist/lib/browser/chunk-CP7E2HRE.mjs.map +0 -7
  306. package/dist/lib/browser/chunk-ERK254BS.mjs +0 -1810
  307. package/dist/lib/browser/chunk-ERK254BS.mjs.map +0 -7
  308. package/dist/lib/browser/chunk-ISCHODBV.mjs +0 -106
  309. package/dist/lib/browser/chunk-ISCHODBV.mjs.map +0 -7
  310. package/dist/lib/browser/chunk-JBB73URQ.mjs +0 -184
  311. package/dist/lib/browser/chunk-JBB73URQ.mjs.map +0 -7
  312. package/dist/lib/browser/chunk-RH7XTXSR.mjs +0 -106
  313. package/dist/lib/browser/chunk-RH7XTXSR.mjs.map +0 -7
  314. package/dist/lib/browser/markdown-YJCSOWXX.mjs +0 -210
  315. package/dist/lib/browser/markdown-YJCSOWXX.mjs.map +0 -7
  316. package/dist/lib/browser/operation-resolver-PROCP5L4.mjs +0 -441
  317. package/dist/lib/browser/operation-resolver-PROCP5L4.mjs.map +0 -7
  318. package/dist/lib/browser/react-root-FHK2SVPU.mjs +0 -25
  319. package/dist/lib/browser/react-root-FHK2SVPU.mjs.map +0 -7
  320. package/dist/lib/browser/react-surface-7MQA6VSH.mjs +0 -111
  321. package/dist/lib/browser/react-surface-7MQA6VSH.mjs.map +0 -7
  322. package/dist/lib/browser/repair-6OZ75AUU.mjs +0 -38
  323. package/dist/lib/browser/repair-6OZ75AUU.mjs.map +0 -7
  324. package/dist/lib/browser/settings-TWKOTGSU.mjs +0 -33
  325. package/dist/lib/browser/settings-TWKOTGSU.mjs.map +0 -7
  326. package/dist/lib/browser/state-SJR2GL5G.mjs +0 -24
  327. package/dist/lib/browser/state-SJR2GL5G.mjs.map +0 -7
  328. package/dist/lib/node-esm/app-graph-builder-IN6VLJBO.mjs +0 -190
  329. package/dist/lib/node-esm/app-graph-builder-IN6VLJBO.mjs.map +0 -7
  330. package/dist/lib/node-esm/blueprint-definition-SXVKFUNV.mjs +0 -19
  331. package/dist/lib/node-esm/blueprint-definition-SXVKFUNV.mjs.map +0 -7
  332. package/dist/lib/node-esm/call-manager-36UAAQCJ.mjs +0 -27
  333. package/dist/lib/node-esm/call-manager-36UAAQCJ.mjs.map +0 -7
  334. package/dist/lib/node-esm/chunk-ABUFOZVX.mjs +0 -33
  335. package/dist/lib/node-esm/chunk-ABUFOZVX.mjs.map +0 -7
  336. package/dist/lib/node-esm/chunk-G7PZNN3Z.mjs +0 -185
  337. package/dist/lib/node-esm/chunk-G7PZNN3Z.mjs.map +0 -7
  338. package/dist/lib/node-esm/chunk-OKVE6CLS.mjs +0 -107
  339. package/dist/lib/node-esm/chunk-OKVE6CLS.mjs.map +0 -7
  340. package/dist/lib/node-esm/chunk-QP3KQOPQ.mjs +0 -1811
  341. package/dist/lib/node-esm/chunk-QP3KQOPQ.mjs.map +0 -7
  342. package/dist/lib/node-esm/chunk-RBRWHRHE.mjs +0 -1818
  343. package/dist/lib/node-esm/chunk-RBRWHRHE.mjs.map +0 -7
  344. package/dist/lib/node-esm/chunk-VBI32FGI.mjs +0 -108
  345. package/dist/lib/node-esm/chunk-VBI32FGI.mjs.map +0 -7
  346. package/dist/lib/node-esm/chunk-WMWUXWAS.mjs +0 -294
  347. package/dist/lib/node-esm/chunk-WMWUXWAS.mjs.map +0 -7
  348. package/dist/lib/node-esm/markdown-6LRP3PAP.mjs +0 -211
  349. package/dist/lib/node-esm/markdown-6LRP3PAP.mjs.map +0 -7
  350. package/dist/lib/node-esm/operation-resolver-LPEPV5BF.mjs +0 -442
  351. package/dist/lib/node-esm/operation-resolver-LPEPV5BF.mjs.map +0 -7
  352. package/dist/lib/node-esm/react-root-P5P4VGQJ.mjs +0 -26
  353. package/dist/lib/node-esm/react-root-P5P4VGQJ.mjs.map +0 -7
  354. package/dist/lib/node-esm/react-surface-M7VI5XG2.mjs +0 -112
  355. package/dist/lib/node-esm/react-surface-M7VI5XG2.mjs.map +0 -7
  356. package/dist/lib/node-esm/repair-6777EPOM.mjs +0 -39
  357. package/dist/lib/node-esm/repair-6777EPOM.mjs.map +0 -7
  358. package/dist/lib/node-esm/settings-5O254B3Z.mjs +0 -34
  359. package/dist/lib/node-esm/settings-5O254B3Z.mjs.map +0 -7
  360. package/dist/lib/node-esm/state-5R3TZJQE.mjs +0 -25
  361. package/dist/lib/node-esm/state-5R3TZJQE.mjs.map +0 -7
  362. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts +0 -6
  363. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +0 -1
  364. package/dist/types/src/capabilities/app-graph-builder/index.d.ts +0 -3
  365. package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +0 -1
  366. package/dist/types/src/capabilities/blueprint-definition/blueprint-definition.d.ts +0 -10
  367. package/dist/types/src/capabilities/blueprint-definition/blueprint-definition.d.ts.map +0 -1
  368. package/dist/types/src/capabilities/blueprint-definition/index.d.ts +0 -3
  369. package/dist/types/src/capabilities/blueprint-definition/index.d.ts.map +0 -1
  370. package/dist/types/src/capabilities/call-manager/call-manager.d.ts +0 -6
  371. package/dist/types/src/capabilities/call-manager/call-manager.d.ts.map +0 -1
  372. package/dist/types/src/capabilities/call-manager/index.d.ts +0 -3
  373. package/dist/types/src/capabilities/call-manager/index.d.ts.map +0 -1
  374. package/dist/types/src/capabilities/markdown/index.d.ts +0 -3
  375. package/dist/types/src/capabilities/markdown/index.d.ts.map +0 -1
  376. package/dist/types/src/capabilities/markdown/markdown.d.ts +0 -5
  377. package/dist/types/src/capabilities/markdown/markdown.d.ts.map +0 -1
  378. package/dist/types/src/capabilities/operation-resolver/index.d.ts +0 -3
  379. package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +0 -1
  380. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +0 -5
  381. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +0 -1
  382. package/dist/types/src/capabilities/react-root/index.d.ts +0 -6
  383. package/dist/types/src/capabilities/react-root/index.d.ts.map +0 -1
  384. package/dist/types/src/capabilities/react-root/react-root.d.ts.map +0 -1
  385. package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
  386. package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
  387. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +0 -5
  388. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
  389. package/dist/types/src/capabilities/repair/index.d.ts +0 -3
  390. package/dist/types/src/capabilities/repair/index.d.ts.map +0 -1
  391. package/dist/types/src/capabilities/repair/repair.d.ts +0 -6
  392. package/dist/types/src/capabilities/repair/repair.d.ts.map +0 -1
  393. package/dist/types/src/capabilities/settings/index.d.ts +0 -3
  394. package/dist/types/src/capabilities/settings/index.d.ts.map +0 -1
  395. package/dist/types/src/capabilities/settings/settings.d.ts +0 -6
  396. package/dist/types/src/capabilities/settings/settings.d.ts.map +0 -1
  397. package/dist/types/src/capabilities/state/index.d.ts +0 -3
  398. package/dist/types/src/capabilities/state/index.d.ts.map +0 -1
  399. package/dist/types/src/capabilities/state/state.d.ts +0 -7
  400. package/dist/types/src/capabilities/state/state.d.ts.map +0 -1
  401. package/dist/types/src/components/CallDebugPanel.d.ts.map +0 -1
  402. package/dist/types/src/components/CallSidebar.d.ts.map +0 -1
  403. package/dist/types/src/components/ChannelContainer.d.ts +0 -13
  404. package/dist/types/src/components/ChannelContainer.d.ts.map +0 -1
  405. package/dist/types/src/components/ChannelContainer.stories.d.ts +0 -164
  406. package/dist/types/src/components/ChannelContainer.stories.d.ts.map +0 -1
  407. package/dist/types/src/components/Chat.stories.d.ts +0 -164
  408. package/dist/types/src/components/Chat.stories.d.ts.map +0 -1
  409. package/dist/types/src/components/ChatContainer.d.ts.map +0 -1
  410. package/dist/types/src/components/Comments.stories.d.ts +0 -162
  411. package/dist/types/src/components/Comments.stories.d.ts.map +0 -1
  412. package/dist/types/src/components/CommentsContainer.d.ts +0 -13
  413. package/dist/types/src/components/CommentsContainer.d.ts.map +0 -1
  414. package/dist/types/src/components/CommentsThreadContainer.d.ts.map +0 -1
  415. package/dist/types/src/components/MessageContainer.d.ts +0 -15
  416. package/dist/types/src/components/MessageContainer.d.ts.map +0 -1
  417. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.d.ts.map +0 -1
  418. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts +0 -166
  419. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts.map +0 -1
  420. package/dist/types/src/components/ThreadCompanion.d.ts +0 -5
  421. package/dist/types/src/components/ThreadCompanion.d.ts.map +0 -1
  422. package/dist/types/src/components/ThreadSettings.d.ts +0 -8
  423. package/dist/types/src/components/ThreadSettings.d.ts.map +0 -1
  424. package/dist/types/src/components/command-extension.d.ts.map +0 -1
  425. package/dist/types/src/components/testing.d.ts.map +0 -1
  426. package/dist/types/src/functions/create-proposals.d.ts +0 -13
  427. package/dist/types/src/functions/create-proposals.d.ts.map +0 -1
  428. package/dist/types/src/functions/index.d.ts +0 -2
  429. package/dist/types/src/functions/index.d.ts.map +0 -1
  430. package/src/capabilities/app-graph-builder/index.ts +0 -7
  431. package/src/capabilities/blueprint-definition/blueprint-definition.ts +0 -24
  432. package/src/capabilities/blueprint-definition/index.ts +0 -7
  433. package/src/capabilities/call-manager/index.ts +0 -7
  434. package/src/capabilities/markdown/index.ts +0 -7
  435. package/src/capabilities/operation-resolver/index.ts +0 -7
  436. package/src/capabilities/operation-resolver/operation-resolver.ts +0 -400
  437. package/src/capabilities/react-root/index.ts +0 -7
  438. package/src/capabilities/react-surface/index.ts +0 -7
  439. package/src/capabilities/repair/index.ts +0 -7
  440. package/src/capabilities/repair/repair.ts +0 -51
  441. package/src/capabilities/settings/index.ts +0 -7
  442. package/src/capabilities/state/index.ts +0 -7
  443. package/src/components/ChatContainer.tsx +0 -152
  444. package/src/components/ThreadSettings.tsx +0 -22
  445. package/src/functions/create-proposals.ts +0 -57
  446. package/src/functions/index.ts +0 -5
@@ -1,176 +1,2197 @@
1
1
  import {
2
- useBlackCanvasStreamTrack,
3
- useDebugMode,
4
- useInaudibleAudioStreamTrack,
5
- useOnEditAnalytics,
6
- useStatus,
7
- useVideoStreamTrack
8
- } from "./chunk-JBB73URQ.mjs";
9
- import {
10
- CALLS_URL,
11
- CallManager,
12
- CallSwarmSynchronizer,
13
- CallsServicePeer,
14
- MediaManager,
15
- SpeakingMonitor,
16
- TrackNameCodec,
17
- codec,
18
- getDeviceList,
19
- getScreenshare,
20
- getUserMediaTrack,
21
- monitorAudioLevel
22
- } from "./chunk-ERK254BS.mjs";
23
- import {
24
- createBlackCanvasStreamTrack,
25
- createInaudibleAudioStreamTrack
26
- } from "./chunk-ISCHODBV.mjs";
27
- import {
28
- Channel_exports,
29
- THREAD_ITEM,
30
- ThreadCapabilities,
31
- ThreadOperation,
32
- meta
33
- } from "./chunk-2FIHSX35.mjs";
2
+ ThreadCapabilities
3
+ } from "./chunk-MESW3R4Q.mjs";
34
4
  import "./chunk-J5LGTIGS.mjs";
35
5
 
36
- // src/ThreadPlugin.tsx
37
- import * as Effect from "effect/Effect";
38
- import { Capability as Capability11, Plugin } from "@dxos/app-framework";
39
- import { AppActivationEvents, AppPlugin } from "@dxos/app-toolkit";
40
- import { Ref, Type as Type2 } from "@dxos/echo";
41
- import { Operation } from "@dxos/operation";
42
- import { ClientCapabilities, ClientEvents } from "@dxos/plugin-client";
43
- import { MarkdownEvents } from "@dxos/plugin-markdown";
44
- import { SpaceCapabilities, SpaceEvents } from "@dxos/plugin-space";
45
- import { translations as threadTranslations } from "@dxos/react-ui-thread";
46
- import { AnchoredTo, Message, Thread } from "@dxos/types";
6
+ // src/calls/call-manager.ts
7
+ import { Atom } from "@effect-atom/atom-react";
8
+ import { Event as Event4, synchronized as synchronized3 } from "@dxos/async";
9
+ import { Resource as Resource5 } from "@dxos/context";
10
+ import { invariant as invariant6 } from "@dxos/invariant";
11
+ import { isNonNullable as isNonNullable2 } from "@dxos/util";
47
12
 
48
- // src/capabilities/app-graph-builder/index.ts
49
- import { Capability } from "@dxos/app-framework";
50
- var AppGraphBuilder = Capability.lazy("AppGraphBuilder", () => import("./app-graph-builder-XFGLMIGK.mjs"));
13
+ // src/calls/call-swarm-synchronizer.ts
14
+ import md5Hex from "md5-hex";
15
+ import { DeferredTask, Event, scheduleTaskInterval, synchronized } from "@dxos/async";
16
+ import { Context, Resource } from "@dxos/context";
17
+ import { generateName } from "@dxos/display-name";
18
+ import { invariant as invariant2 } from "@dxos/invariant";
19
+ import { PublicKey } from "@dxos/keys";
20
+ import { log } from "@dxos/log";
21
+ import { buf as buf2 } from "@dxos/protocols/buf";
22
+ import { ActivitySchema } from "@dxos/protocols/buf/dxos/edge/calls_pb";
23
+ import { ConnectionState } from "@dxos/protocols/proto/dxos/edge/messenger";
24
+ import { isNonNullable } from "@dxos/util";
51
25
 
52
- // src/capabilities/blueprint-definition/index.ts
53
- import { Capability as Capability2 } from "@dxos/app-framework";
54
- var BlueprintDefinition = Capability2.lazy("BlueprintDefinition", () => import("./blueprint-definition-ACPH22F7.mjs"));
26
+ // src/calls/types.ts
27
+ import { invariant } from "@dxos/invariant";
28
+ import { buf } from "@dxos/protocols/buf";
29
+ import { UserStateSchema } from "@dxos/protocols/buf/dxos/edge/calls_pb";
30
+ var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/calls/types.ts";
31
+ var CALLS_URL = "https://calls-service.dxos.workers.dev";
32
+ var codec = {
33
+ encode: (message) => {
34
+ return buf.toBinary(UserStateSchema, buf.create(UserStateSchema, message));
35
+ },
36
+ decode: (message) => {
37
+ return buf.fromBinary(UserStateSchema, message);
38
+ }
39
+ };
40
+ var TrackNameCodec = {
41
+ encode: (trackData) => {
42
+ invariant(trackData.sessionId, void 0, {
43
+ F: __dxlog_file,
44
+ L: 65,
45
+ S: void 0,
46
+ A: [
47
+ "trackData.sessionId",
48
+ ""
49
+ ]
50
+ });
51
+ invariant(trackData.trackName, void 0, {
52
+ F: __dxlog_file,
53
+ L: 66,
54
+ S: void 0,
55
+ A: [
56
+ "trackData.trackName",
57
+ ""
58
+ ]
59
+ });
60
+ invariant(trackData.mid, void 0, {
61
+ F: __dxlog_file,
62
+ L: 67,
63
+ S: void 0,
64
+ A: [
65
+ "trackData.mid",
66
+ ""
67
+ ]
68
+ });
69
+ return trackData.sessionId + "/" + trackData.trackName + "/" + trackData.mid;
70
+ },
71
+ decode: (name) => {
72
+ const [sessionId, trackName, mid] = name.split("/");
73
+ return {
74
+ sessionId,
75
+ trackName,
76
+ location: "remote",
77
+ mid
78
+ };
79
+ }
80
+ };
55
81
 
56
- // src/capabilities/call-manager/index.ts
57
- import { Capability as Capability3 } from "@dxos/app-framework";
58
- var CallManager2 = Capability3.lazy("CallManager", () => import("./call-manager-GDGIKJKN.mjs"));
82
+ // src/calls/call-swarm-synchronizer.ts
83
+ function _ts_decorate(decorators, target, key, desc) {
84
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
85
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
86
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
87
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
88
+ }
89
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/calls/call-swarm-synchronizer.ts";
90
+ var DISCONNECTED_ABRUPT_TIMEOUT = 1e4;
91
+ var CallSwarmSynchronizer = class extends Resource {
92
+ stateUpdated = new Event();
93
+ _state = {
94
+ activities: {}
95
+ };
96
+ _networkService;
97
+ _lastSwarmEvent = void 0;
98
+ _reconcileSwarmStateTask = void 0;
99
+ _identityKey = void 0;
100
+ _deviceKey = void 0;
101
+ _displayName = void 0;
102
+ _swarmCtx = void 0;
103
+ _sendStateTask = void 0;
104
+ constructor({ networkService }) {
105
+ super();
106
+ this._networkService = networkService;
107
+ }
108
+ /**
109
+ * @internal
110
+ */
111
+ _getState() {
112
+ return this._state;
113
+ }
114
+ setRaisedHand(raisedHand) {
115
+ if (this._state.raisedHand === raisedHand) {
116
+ return;
117
+ }
118
+ this._state.raisedHand = raisedHand;
119
+ this._notifyAndSchedule();
120
+ }
121
+ setSpeaking(speaking) {
122
+ if (this._state.speaking === speaking) {
123
+ return;
124
+ }
125
+ this._state.speaking = speaking;
126
+ this._notifyAndSchedule();
127
+ }
128
+ setJoined(joined) {
129
+ if (this._state.joined === joined) {
130
+ return;
131
+ }
132
+ this._state.joined = joined;
133
+ this._notifyAndSchedule();
134
+ }
135
+ setTracks(tracks) {
136
+ this._state.tracks = {
137
+ ...this._state.tracks,
138
+ ...tracks
139
+ };
140
+ this._notifyAndSchedule();
141
+ }
142
+ setActivity(key, payload) {
143
+ const lamportTimestamp = LamportTimestampCrdt.increment(this._state.activities?.[key]?.lamportTimestamp ?? {
144
+ id: this._deviceKey
145
+ });
146
+ this._state.activities[key] = {
147
+ lamportTimestamp,
148
+ payload
149
+ };
150
+ this._notifyAndSchedule();
151
+ }
152
+ /**
153
+ * @internal
154
+ */
155
+ _setIdentity(identity) {
156
+ this._identityKey = identity.identityKey.toHex();
157
+ this._displayName = identity.profile?.displayName ?? generateName(identity.identityKey.toHex());
158
+ }
159
+ /**
160
+ * @internal
161
+ */
162
+ _setDevice(device) {
163
+ this._deviceKey = device.deviceKey.toHex();
164
+ }
165
+ /**
166
+ * @internal
167
+ */
168
+ _setRoomId(roomId) {
169
+ if (this._swarmCtx) {
170
+ log.verbose("joined to a different room", {
171
+ roomId
172
+ }, {
173
+ F: __dxlog_file2,
174
+ L: 152,
175
+ S: this,
176
+ C: (f, a) => f(...a)
177
+ });
178
+ return;
179
+ }
180
+ this._state.roomId = roomId;
181
+ }
182
+ async _open() {
183
+ this._sendStateTask = new DeferredTask(this._ctx, async () => {
184
+ await this._sendState();
185
+ });
186
+ this._reconcileSwarmStateTask = new DeferredTask(this._ctx, async () => {
187
+ await this._reconcileSwarmState();
188
+ });
189
+ }
190
+ async _close() {
191
+ this._sendStateTask = void 0;
192
+ this._reconcileSwarmStateTask = void 0;
193
+ }
194
+ async join() {
195
+ invariant2(this._state.roomId, void 0, {
196
+ F: __dxlog_file2,
197
+ L: 176,
198
+ S: this,
199
+ A: [
200
+ "this._state.roomId",
201
+ ""
202
+ ]
203
+ });
204
+ invariant2(!this._swarmCtx, "Already joined", {
205
+ F: __dxlog_file2,
206
+ L: 177,
207
+ S: this,
208
+ A: [
209
+ "!this._swarmCtx",
210
+ "'Already joined'"
211
+ ]
212
+ });
213
+ this._swarmCtx = new Context(void 0, {
214
+ F: __dxlog_file2,
215
+ L: 179
216
+ });
217
+ const topic = getTopic(this._state.roomId);
218
+ log("joining swarm", {
219
+ topic,
220
+ peer: {
221
+ identityKey: this._identityKey,
222
+ peerKey: this._deviceKey
223
+ }
224
+ }, {
225
+ F: __dxlog_file2,
226
+ L: 181,
227
+ S: this,
228
+ C: (f, a) => f(...a)
229
+ });
230
+ const stream = this._networkService.subscribeSwarmState({
231
+ topic
232
+ });
233
+ stream.subscribe((event) => this._processSwarmEvent(event));
234
+ const cleanup = () => {
235
+ void stream.close();
236
+ if (topic && this._identityKey && this._deviceKey) {
237
+ log("leaving swarm", {
238
+ topic,
239
+ peer: {
240
+ identityKey: this._identityKey,
241
+ peerKey: this._deviceKey
242
+ }
243
+ }, {
244
+ F: __dxlog_file2,
245
+ L: 188,
246
+ S: this,
247
+ C: (f, a) => f(...a)
248
+ });
249
+ void this._networkService.leaveSwarm({
250
+ topic,
251
+ peer: {
252
+ identityKey: this._identityKey,
253
+ peerKey: this._deviceKey
254
+ }
255
+ }).catch((err) => log.catch(err, void 0, {
256
+ F: __dxlog_file2,
257
+ L: 194,
258
+ S: this,
259
+ C: (f, a) => f(...a)
260
+ }));
261
+ }
262
+ window.removeEventListener("beforeunload", cleanup);
263
+ };
264
+ window.addEventListener("beforeunload", cleanup);
265
+ this._swarmCtx.onDispose(cleanup);
266
+ this._notifyAndSchedule();
267
+ }
268
+ async leave() {
269
+ if (!this._swarmCtx) {
270
+ return;
271
+ }
272
+ await this._swarmCtx.dispose();
273
+ this._swarmCtx = void 0;
274
+ this._state.users = void 0;
275
+ this._state.self = void 0;
276
+ }
277
+ async querySwarm(roomId) {
278
+ const topic = getTopic(roomId);
279
+ const swarm = await this._networkService.querySwarm({
280
+ topic
281
+ });
282
+ return swarm.peers ?? [];
283
+ }
284
+ /**
285
+ * Notify and schedule send state task.
286
+ */
287
+ _notifyAndSchedule() {
288
+ this.stateUpdated.emit(this._state);
289
+ if (this._state.joined) {
290
+ this._sendStateTask?.schedule();
291
+ }
292
+ }
293
+ async _sendState() {
294
+ if (!this._state.roomId || !this._identityKey || !this._deviceKey || !this._state.joined) {
295
+ return;
296
+ }
297
+ const state = {
298
+ ...this._state,
299
+ id: this._deviceKey,
300
+ name: this._displayName,
301
+ activities: this._state.activities ? Object.fromEntries(Object.entries(this._state.activities).map(([key, activity]) => [
302
+ key,
303
+ buf2.create(ActivitySchema, activity)
304
+ ])) : {}
305
+ };
306
+ await this._networkService.joinSwarm({
307
+ topic: getTopic(this._state.roomId),
308
+ peer: {
309
+ identityKey: this._identityKey,
310
+ peerKey: this._deviceKey,
311
+ state: codec.encode(state)
312
+ }
313
+ });
314
+ }
315
+ _processSwarmEvent(swarmEvent) {
316
+ if (!this._state.joined) {
317
+ return;
318
+ }
319
+ this._lastSwarmEvent = swarmEvent;
320
+ this._reconcileSwarmStateTask.schedule();
321
+ }
322
+ async _reconcileSwarmState() {
323
+ const swarmEvent = this._lastSwarmEvent;
324
+ invariant2(swarmEvent, void 0, {
325
+ F: __dxlog_file2,
326
+ L: 273,
327
+ S: this,
328
+ A: [
329
+ "swarmEvent",
330
+ ""
331
+ ]
332
+ });
333
+ const peers = [
334
+ ...swarmEvent.peers ?? [],
335
+ ...(swarmEvent.inactivePeers ?? []).filter(({ disconnected, connectionState }) => connectionState === ConnectionState.DISCONNECTED_ABRUPT && disconnected && disconnected > Date.now() - DISCONNECTED_ABRUPT_TIMEOUT)
336
+ ].sort((peer1, peer2) => peer1.peerKey.localeCompare(peer2.peerKey));
337
+ const users = peers.map((peer) => {
338
+ try {
339
+ return codec.decode(peer.state);
340
+ } catch (error) {
341
+ log.error("error decoding peer state", {
342
+ error,
343
+ peer
344
+ }, {
345
+ F: __dxlog_file2,
346
+ L: 290,
347
+ S: this,
348
+ C: (f, a) => f(...a)
349
+ });
350
+ return void 0;
351
+ }
352
+ }).filter(isNonNullable);
353
+ this._state.users = users;
354
+ this._state.self = users.find((user) => user.id === this._deviceKey);
355
+ log("reconciling swarm state", {
356
+ users
357
+ }, {
358
+ F: __dxlog_file2,
359
+ L: 297,
360
+ S: this,
361
+ C: (f, a) => f(...a)
362
+ });
363
+ if (users.length === 0) {
364
+ return;
365
+ }
366
+ const activityKeys = new Set(users.flatMap((user) => Object.keys(user.activities)));
367
+ [
368
+ ...activityKeys
369
+ ].forEach((key) => {
370
+ const activities = users.map((user) => user.activities?.[key]).filter(isNonNullable);
371
+ const lastActivity = LamportTimestampCrdt.getLastState(activities);
372
+ if (lastActivity && lastActivity.lamportTimestamp.version > (this._state.activities[key]?.lamportTimestamp?.version ?? 0)) {
373
+ this._state.activities[key] = lastActivity;
374
+ }
375
+ });
376
+ this.stateUpdated.emit(this._state);
377
+ if (peers.some((peer) => peer.connectionState !== ConnectionState.CONNECTED)) {
378
+ scheduleTaskInterval(this._ctx, async () => this._reconcileSwarmStateTask.schedule(), Math.min(DISCONNECTED_ABRUPT_TIMEOUT / 2, 1e3));
379
+ }
380
+ }
381
+ };
382
+ _ts_decorate([
383
+ synchronized
384
+ ], CallSwarmSynchronizer.prototype, "join", null);
385
+ _ts_decorate([
386
+ synchronized
387
+ ], CallSwarmSynchronizer.prototype, "leave", null);
388
+ var LamportTimestampCrdt = class {
389
+ static getLastState(states) {
390
+ const maxTimestamp = Math.max(...states.map((state) => state.lamportTimestamp?.version ?? 0));
391
+ const sortedStates = states.filter((state) => state.lamportTimestamp && state.lamportTimestamp.version === maxTimestamp && state.lamportTimestamp.id).sort((a, b) => a.lamportTimestamp.id.localeCompare(b.lamportTimestamp.id));
392
+ return sortedStates[0];
393
+ }
394
+ static increment(timestamp) {
395
+ return {
396
+ ...timestamp ?? {},
397
+ version: (timestamp?.version ?? 0) + 1
398
+ };
399
+ }
400
+ };
401
+ var getTopic = (roomId) => PublicKey.fromHex(md5Hex(roomId));
59
402
 
60
- // src/capabilities/markdown/index.ts
61
- import { Capability as Capability4 } from "@dxos/app-framework";
62
- var Markdown = Capability4.lazy("Markdown", () => import("./markdown-YJCSOWXX.mjs"));
403
+ // src/calls/media-manager.ts
404
+ import { DeferredTask as DeferredTask3, Event as Event3, sleep as sleep2, synchronized as synchronized2 } from "@dxos/async";
405
+ import { Resource as Resource4, cancelWithContext as cancelWithContext2 } from "@dxos/context";
406
+ import { invariant as invariant5 } from "@dxos/invariant";
407
+ import { log as log4 } from "@dxos/log";
63
408
 
64
- // src/capabilities/operation-resolver/index.ts
65
- import { Capability as Capability5 } from "@dxos/app-framework";
66
- var OperationResolver = Capability5.lazy("OperationResolver", () => import("./operation-resolver-PROCP5L4.mjs"));
409
+ // src/calls/speaking-monitor.ts
410
+ import { DeferredTask as DeferredTask2, Event as Event2, sleep } from "@dxos/async";
411
+ import { Resource as Resource3 } from "@dxos/context";
67
412
 
68
- // src/capabilities/react-root/index.ts
69
- import { Capability as Capability6 } from "@dxos/app-framework";
70
- var ReactRoot = Capability6.lazy("ReactRoot", () => import("./react-root-FHK2SVPU.mjs"));
413
+ // src/calls/util/audio.ts
414
+ var monitorAudioLevel = ({ mediaStreamTrack, intervalMs = 1e3 / 10, onMeasure }) => {
415
+ let timeout = -1;
416
+ let interval = -1;
417
+ const audioContext = new AudioContext();
418
+ const stream = new MediaStream();
419
+ stream.addTrack(mediaStreamTrack);
420
+ const mediaStreamAudioSourceNode = audioContext.createMediaStreamSource(stream);
421
+ const analyserNode = audioContext.createAnalyser();
422
+ mediaStreamAudioSourceNode.connect(analyserNode);
423
+ analyserNode.fftSize = 32;
424
+ const pcmData = new Float32Array(analyserNode.fftSize);
425
+ let peak = 0;
426
+ interval = window.setInterval(() => {
427
+ onMeasure(peak);
428
+ peak = 0;
429
+ }, intervalMs);
430
+ const tick = () => {
431
+ timeout = window.setTimeout(() => {
432
+ analyserNode.getFloatTimeDomainData(pcmData);
433
+ let sumSquares = 0;
434
+ for (const amplitude of pcmData) {
435
+ sumSquares += amplitude * amplitude;
436
+ }
437
+ const current = Math.sqrt(sumSquares / pcmData.length);
438
+ if (current > peak) {
439
+ peak = current;
440
+ }
441
+ tick();
442
+ }, intervalMs);
443
+ };
444
+ tick();
445
+ return () => {
446
+ mediaStreamAudioSourceNode.disconnect();
447
+ analyserNode.disconnect();
448
+ void audioContext.close();
449
+ clearInterval(interval);
450
+ clearTimeout(timeout);
451
+ stream.removeTrack(mediaStreamTrack);
452
+ };
453
+ };
71
454
 
72
- // src/capabilities/react-surface/index.ts
73
- import { Capability as Capability7 } from "@dxos/app-framework";
74
- var ReactSurface = Capability7.lazy("ReactSurface", () => import("./react-surface-7MQA6VSH.mjs"));
455
+ // src/calls/util/calls-service.ts
456
+ import { PersistentLifecycle, Trigger, scheduleTask } from "@dxos/async";
457
+ import { Resource as Resource2 } from "@dxos/context";
458
+ import { invariant as invariant3 } from "@dxos/invariant";
459
+ import { log as log2 } from "@dxos/log";
75
460
 
76
- // src/capabilities/repair/index.ts
77
- import { Capability as Capability8 } from "@dxos/app-framework";
78
- var Repair = Capability8.lazy("Repair", () => import("./repair-6OZ75AUU.mjs"));
461
+ // src/calls/util/history-cache.ts
462
+ var HistoryCache = class {
463
+ _limit;
464
+ _messages;
465
+ constructor(limit = 100) {
466
+ this._limit = limit;
467
+ this._messages = [];
468
+ }
469
+ push(...messages) {
470
+ if (this._messages.length >= this._limit) {
471
+ this._messages.shift();
472
+ }
473
+ this._messages.push(...messages);
474
+ }
475
+ get() {
476
+ return this._messages;
477
+ }
478
+ };
79
479
 
80
- // src/capabilities/settings/index.ts
81
- import { Capability as Capability9 } from "@dxos/app-framework";
82
- var ThreadSettings = Capability9.lazy("ThreadSettings", () => import("./settings-TWKOTGSU.mjs"));
480
+ // src/calls/util/task-scheduling.ts
481
+ var DefaultBatchSizeLimit = 64;
482
+ var FIFOScheduler = class {
483
+ #schedulerChain;
484
+ constructor() {
485
+ this.#schedulerChain = Promise.resolve();
486
+ }
487
+ schedule(task) {
488
+ return new Promise((resolve, reject) => {
489
+ this.#schedulerChain = this.#schedulerChain.then(async () => {
490
+ try {
491
+ resolve(await task());
492
+ } catch (error) {
493
+ reject(error);
494
+ }
495
+ });
496
+ });
497
+ }
498
+ };
499
+ var BulkRequestDispatcher = class {
500
+ #currentBatch;
501
+ #currentBulkResponse;
502
+ #batchSizeLimit;
503
+ constructor(batchSizeLimit = DefaultBatchSizeLimit) {
504
+ this.#currentBatch = [];
505
+ this.#currentBulkResponse = null;
506
+ this.#batchSizeLimit = batchSizeLimit;
507
+ }
508
+ /**
509
+ * Returns a bulk response promise.
510
+ * At the event loop iteration end, the accumulated entries will be dispatched as a bulk request.
511
+ */
512
+ doBulkRequest(params, bulkRequestFunc) {
513
+ if (this.#currentBatch.length >= this.#batchSizeLimit) {
514
+ this.#currentBatch = [];
515
+ this.#currentBulkResponse = null;
516
+ }
517
+ this.#currentBatch.push(params);
518
+ if (this.#currentBulkResponse != null) {
519
+ return this.#currentBulkResponse;
520
+ }
521
+ const batch = this.#currentBatch;
522
+ this.#currentBulkResponse = new Promise((resolve, reject) => {
523
+ setTimeout(() => {
524
+ this.#currentBulkResponse = null;
525
+ const batchCopy = batch.splice(0, batch.length);
526
+ bulkRequestFunc(batchCopy).then((result) => {
527
+ resolve(result);
528
+ }).catch((err) => {
529
+ reject(err);
530
+ });
531
+ }, 0);
532
+ });
533
+ return this.#currentBulkResponse;
534
+ }
535
+ };
83
536
 
84
- // src/capabilities/state/index.ts
85
- import { Capability as Capability10 } from "@dxos/app-framework";
86
- var ThreadState = Capability10.lazy("ThreadState", () => import("./state-SJR2GL5G.mjs"));
537
+ // src/calls/util/calls-service.ts
538
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/calls/util/calls-service.ts";
539
+ var NETWORK_TIMEOUT = 5e3;
540
+ var CallsServicePeer = class extends Resource2 {
541
+ history = new HistoryCache(100);
542
+ _persistentLifecycle = new PersistentLifecycle({
543
+ start: () => this._startSession(),
544
+ stop: (session) => this._stopSession(session)
545
+ });
546
+ _config;
547
+ taskScheduler = new FIFOScheduler();
548
+ pushTrackDispatcher = new BulkRequestDispatcher(32);
549
+ pullTrackDispatcher = new BulkRequestDispatcher(32);
550
+ closeTrackDispatcher = new BulkRequestDispatcher(32);
551
+ constructor(config) {
552
+ super();
553
+ this._config = config;
554
+ }
555
+ async _open(ctx) {
556
+ await this._persistentLifecycle.open(ctx);
557
+ }
558
+ async _close() {
559
+ await this._persistentLifecycle.close();
560
+ }
561
+ get session() {
562
+ return this._persistentLifecycle.state;
563
+ }
564
+ async _startSession() {
565
+ const peerConnection = await this._createRtcConnection();
566
+ const sessionId = await this._initiateCallSession();
567
+ return {
568
+ sessionId,
569
+ peerConnection
570
+ };
571
+ }
572
+ async _stopSession(session) {
573
+ session.peerConnection.close();
574
+ }
575
+ async _createRtcConnection() {
576
+ const peerConnection = new RTCPeerConnection({
577
+ iceServers: this._config.iceServers,
578
+ bundlePolicy: "max-bundle"
579
+ });
580
+ peerConnection.addEventListener("connectionstatechange", () => {
581
+ if (peerConnection.connectionState === "failed" || peerConnection.connectionState === "closed") {
582
+ log2.info("calls connection failed", {
583
+ state: peerConnection.connectionState
584
+ }, {
585
+ F: __dxlog_file3,
586
+ L: 120,
587
+ S: this,
588
+ C: (f, a) => f(...a)
589
+ });
590
+ void this._persistentLifecycle.scheduleRestart();
591
+ }
592
+ });
593
+ let iceTimeout = -1;
594
+ peerConnection.addEventListener("iceconnectionstatechange", () => {
595
+ clearTimeout(iceTimeout);
596
+ if (peerConnection.iceConnectionState === "failed" || peerConnection.iceConnectionState === "closed") {
597
+ log2.info("calls connection to ICEs failed", {
598
+ state: peerConnection.iceConnectionState
599
+ }, {
600
+ F: __dxlog_file3,
601
+ L: 129,
602
+ S: this,
603
+ C: (f, a) => f(...a)
604
+ });
605
+ void this._persistentLifecycle.scheduleRestart();
606
+ } else if (peerConnection.iceConnectionState === "disconnected") {
607
+ const timeoutSeconds = 7;
608
+ iceTimeout = window.setTimeout(() => {
609
+ if (peerConnection.iceConnectionState === "connected") {
610
+ log2.info("calls iceConnectionState is connected", void 0, {
611
+ F: __dxlog_file3,
612
+ L: 138,
613
+ S: this,
614
+ C: (f, a) => f(...a)
615
+ });
616
+ return;
617
+ }
618
+ log2.info("calls iceConnectionState timed out", {
619
+ state: peerConnection.iceConnectionState,
620
+ timeoutSeconds
621
+ }, {
622
+ F: __dxlog_file3,
623
+ L: 142,
624
+ S: this,
625
+ C: (f, a) => f(...a)
626
+ });
627
+ void this._persistentLifecycle.scheduleRestart();
628
+ }, timeoutSeconds * 1e3);
629
+ }
630
+ });
631
+ return peerConnection;
632
+ }
633
+ async _initiateCallSession() {
634
+ log2("creating new session", void 0, {
635
+ F: __dxlog_file3,
636
+ L: 152,
637
+ S: this,
638
+ C: (f, a) => f(...a)
639
+ });
640
+ const { sessionId } = await this._fetch("/sessions/new?SESSION", {
641
+ method: "POST"
642
+ });
643
+ return sessionId;
644
+ }
645
+ async _fetch(relativePath, requestInit) {
646
+ this.history.push({
647
+ endpoint: relativePath,
648
+ type: "request",
649
+ time: (/* @__PURE__ */ new Date()).toISOString(),
650
+ method: requestInit?.method ?? "GET",
651
+ body: requestInit?.body
652
+ });
653
+ const response = await fetch(`${this._config.apiBase}${relativePath}`, {
654
+ ...requestInit,
655
+ redirect: "manual"
656
+ });
657
+ if (response.status >= 400) {
658
+ log2.error("error while fetching from Calls service", {
659
+ status: response.status,
660
+ text: await response.text()
661
+ }, {
662
+ F: __dxlog_file3,
663
+ L: 168,
664
+ S: this,
665
+ C: (f, a) => f(...a)
666
+ });
667
+ throw new Error("Error while fetching from Calls service");
668
+ }
669
+ try {
670
+ const data = await response.clone().json();
671
+ this.history.push({
672
+ endpoint: relativePath,
673
+ type: "response",
674
+ time: (/* @__PURE__ */ new Date()).toISOString(),
675
+ status: response.status,
676
+ json: data
677
+ });
678
+ if (data.errorCode) {
679
+ throw new Error(data.errorDescription);
680
+ }
681
+ return data;
682
+ } catch (error) {
683
+ const text = await response.text();
684
+ this.history.push({
685
+ endpoint: relativePath,
686
+ type: "response",
687
+ time: (/* @__PURE__ */ new Date()).toISOString(),
688
+ status: response.status,
689
+ text
690
+ });
691
+ log2.error("Error parsing response from Calls service", {
692
+ error,
693
+ text,
694
+ status: response.status
695
+ }, {
696
+ F: __dxlog_file3,
697
+ L: 195,
698
+ S: this,
699
+ C: (f, a) => f(...a)
700
+ });
701
+ throw error;
702
+ }
703
+ }
704
+ async _pushTrackInBulk({ ctx, peerConnection, transceiver, sessionId, trackName }) {
705
+ log2.verbose("pushing track ", trackName, {
706
+ F: __dxlog_file3,
707
+ L: 217,
708
+ S: this,
709
+ C: (f, a) => f(...a)
710
+ });
711
+ const pushedTrackPromise = this.pushTrackDispatcher.doBulkRequest({
712
+ trackName,
713
+ transceiver
714
+ }, (tracks) => this.taskScheduler.schedule(async () => {
715
+ const offer = await peerConnection.createOffer();
716
+ offer.sdp = offer.sdp?.replace("useinbandfec=1", "usedtx=1;useinbandfec=1");
717
+ await peerConnection.setLocalDescription(offer);
718
+ const response = await this._fetch(`/sessions/${sessionId}/tracks/new?PUSHING`, {
719
+ method: "POST",
720
+ body: JSON.stringify({
721
+ sessionDescription: {
722
+ sdp: offer.sdp,
723
+ type: "offer"
724
+ },
725
+ tracks: tracks.map(({ trackName: trackName2, transceiver: transceiver2 }) => ({
726
+ trackName: trackName2,
727
+ mid: transceiver2.mid,
728
+ location: "local"
729
+ }))
730
+ })
731
+ });
732
+ invariant3(response.tracks !== void 0, void 0, {
733
+ F: __dxlog_file3,
734
+ L: 242,
735
+ S: this,
736
+ A: [
737
+ "response.tracks !== undefined",
738
+ ""
739
+ ]
740
+ });
741
+ if (!response.errorCode) {
742
+ await peerConnection.setRemoteDescription(new RTCSessionDescription(response.sessionDescription));
743
+ await peerConnectionIsConnected(peerConnection);
744
+ }
745
+ return {
746
+ tracks: response.tracks
747
+ };
748
+ })).then(async ({ tracks }) => {
749
+ const trackData = tracks.find((t) => t.mid === transceiver.mid);
750
+ if (trackData) {
751
+ return {
752
+ ...trackData,
753
+ sessionId,
754
+ location: "remote"
755
+ };
756
+ } else {
757
+ log2.error("missing track data", void 0, {
758
+ F: __dxlog_file3,
759
+ L: 266,
760
+ S: this,
761
+ C: (f, a) => f(...a)
762
+ });
763
+ }
764
+ });
765
+ const onDispose = async () => {
766
+ if (transceiver.mid) {
767
+ await this._closeTrackInBulk(peerConnection, transceiver.mid, sessionId);
768
+ }
769
+ };
770
+ ctx?.onDispose(async () => await onDispose());
771
+ this._ctx.onDispose(() => onDispose());
772
+ return pushedTrackPromise;
773
+ }
774
+ async pushTrack({ track, encodings = [], ctx, previousTrack }) {
775
+ await this.waitUntilOpen();
776
+ invariant3(this.session, void 0, {
777
+ F: __dxlog_file3,
778
+ L: 294,
779
+ S: this,
780
+ A: [
781
+ "this.session",
782
+ ""
783
+ ]
784
+ });
785
+ log2("trying to push track", {
786
+ track,
787
+ previousTrack,
788
+ encodings
789
+ }, {
790
+ F: __dxlog_file3,
791
+ L: 295,
792
+ S: this,
793
+ C: (f, a) => f(...a)
794
+ });
795
+ if (previousTrack) {
796
+ const transceiver2 = this.session.peerConnection.getTransceivers().find((t) => t.mid === previousTrack.mid);
797
+ if (transceiver2?.sender.track === track) {
798
+ log2.verbose("track already pushed", {
799
+ track,
800
+ previousTrack,
801
+ transceiver: transceiver2
802
+ }, {
803
+ F: __dxlog_file3,
804
+ L: 299,
805
+ S: this,
806
+ C: (f, a) => f(...a)
807
+ });
808
+ return previousTrack;
809
+ } else if (transceiver2) {
810
+ log2.verbose("replacing track", {
811
+ track,
812
+ previousTrack,
813
+ transceiver: transceiver2
814
+ }, {
815
+ F: __dxlog_file3,
816
+ L: 302,
817
+ S: this,
818
+ C: (f, a) => f(...a)
819
+ });
820
+ transceiver2.sender.replaceTrack(track).catch((err) => log2.catch(err, void 0, {
821
+ F: __dxlog_file3,
822
+ L: 303,
823
+ S: this,
824
+ C: (f, a) => f(...a)
825
+ }));
826
+ return previousTrack;
827
+ }
828
+ }
829
+ invariant3(track, void 0, {
830
+ F: __dxlog_file3,
831
+ L: 307,
832
+ S: this,
833
+ A: [
834
+ "track",
835
+ ""
836
+ ]
837
+ });
838
+ const stableId = crypto.randomUUID();
839
+ const transceiver = this.session.peerConnection.addTransceiver(track, {
840
+ direction: "sendonly"
841
+ });
842
+ log2.verbose("creating transceiver", void 0, {
843
+ F: __dxlog_file3,
844
+ L: 312,
845
+ S: this,
846
+ C: (f, a) => f(...a)
847
+ });
848
+ const pushedTrackData = await this._pushTrackInBulk({
849
+ ctx,
850
+ peerConnection: this.session.peerConnection,
851
+ transceiver,
852
+ sessionId: this.session.sessionId,
853
+ trackName: stableId
854
+ });
855
+ invariant3(pushedTrackData, void 0, {
856
+ F: __dxlog_file3,
857
+ L: 321,
858
+ S: this,
859
+ A: [
860
+ "pushedTrackData",
861
+ ""
862
+ ]
863
+ });
864
+ const parameters = transceiver.sender.getParameters();
865
+ encodings.forEach((encoding, i) => {
866
+ const existing = parameters.encodings[i];
867
+ parameters.encodings[i] = {
868
+ ...existing,
869
+ ...encoding
870
+ };
871
+ });
872
+ transceiver.sender.setParameters(parameters).catch((err) => log2.catch(err, void 0, {
873
+ F: __dxlog_file3,
874
+ L: 328,
875
+ S: this,
876
+ C: (f, a) => f(...a)
877
+ }));
878
+ return pushedTrackData;
879
+ }
880
+ // TODO(mykola): Add retry logic if the tracks fails to pull.
881
+ async _pullTrackInBulk({ peerConnection, sessionId, trackData, ctx }) {
882
+ let mid = "";
883
+ log2("pulling track", {
884
+ trackName: trackData.trackName
885
+ }, {
886
+ F: __dxlog_file3,
887
+ L: 346,
888
+ S: this,
889
+ C: (f, a) => f(...a)
890
+ });
891
+ const pulledTrackPromise = this.pullTrackDispatcher.doBulkRequest(trackData, (tracks) => this.taskScheduler.schedule(async () => {
892
+ const newTrackResponse = await this._fetch(`/sessions/${sessionId}/tracks/new?PULLING`, {
893
+ method: "POST",
894
+ body: JSON.stringify({
895
+ tracks
896
+ })
897
+ });
898
+ if (newTrackResponse.errorCode) {
899
+ throw new Error(newTrackResponse.errorDescription);
900
+ }
901
+ invariant3(newTrackResponse.tracks, void 0, {
902
+ F: __dxlog_file3,
903
+ L: 359,
904
+ S: this,
905
+ A: [
906
+ "newTrackResponse.tracks",
907
+ ""
908
+ ]
909
+ });
910
+ const trackMap = tracks.reduce((acc, track) => {
911
+ const pulledTrackData = newTrackResponse.tracks?.find((t) => t.trackName === track.trackName && t.sessionId === track.sessionId);
912
+ if (pulledTrackData && pulledTrackData.mid) {
913
+ acc.set(track.trackName, {
914
+ mid: pulledTrackData.mid,
915
+ resolvedTrack: resolveTrack(peerConnection, (t) => t.mid === pulledTrackData.mid)
916
+ });
917
+ }
918
+ return acc;
919
+ }, /* @__PURE__ */ new Map());
920
+ if (newTrackResponse.requiresImmediateRenegotiation) {
921
+ await peerConnection.setRemoteDescription(new RTCSessionDescription(newTrackResponse.sessionDescription));
922
+ const answer = await peerConnection.createAnswer();
923
+ await peerConnection.setLocalDescription(answer);
924
+ const renegotiationResponse = await this._fetch(`/sessions/${sessionId}/renegotiate`, {
925
+ method: "PUT",
926
+ body: JSON.stringify({
927
+ sessionDescription: {
928
+ type: "answer",
929
+ sdp: peerConnection.currentLocalDescription?.sdp
930
+ }
931
+ })
932
+ });
933
+ if (renegotiationResponse.errorCode) {
934
+ throw new Error(renegotiationResponse.errorDescription);
935
+ } else {
936
+ await peerConnectionIsConnected(peerConnection);
937
+ }
938
+ }
939
+ return {
940
+ trackMap
941
+ };
942
+ })).then(({ trackMap }) => {
943
+ const trackInfo = trackMap.get(trackData.trackName);
944
+ if (trackInfo) {
945
+ return trackInfo.resolvedTrack.then((track) => {
946
+ mid = trackInfo.mid;
947
+ return track;
948
+ }).catch((err) => log2.catch(err, void 0, {
949
+ F: __dxlog_file3,
950
+ L: 411,
951
+ S: this,
952
+ C: (f, a) => f(...a)
953
+ }));
954
+ } else {
955
+ log2.info("missing track info", {
956
+ trackData,
957
+ availableTracks: Array.from(trackMap.keys())
958
+ }, {
959
+ F: __dxlog_file3,
960
+ L: 413,
961
+ S: this,
962
+ C: (f, a) => f(...a)
963
+ });
964
+ }
965
+ });
966
+ const onDispose = async () => {
967
+ if (mid) {
968
+ log2("closing pulled track ", trackData.trackName, {
969
+ F: __dxlog_file3,
970
+ L: 419,
971
+ S: this,
972
+ C: (f, a) => f(...a)
973
+ });
974
+ await this._closeTrackInBulk(peerConnection, mid, sessionId);
975
+ mid = "";
976
+ }
977
+ };
978
+ this._ctx.onDispose(() => onDispose());
979
+ ctx?.onDispose(() => onDispose());
980
+ return pulledTrackPromise;
981
+ }
982
+ async pullTrack({ ctx, trackData }) {
983
+ await this.waitUntilOpen();
984
+ invariant3(this.session, void 0, {
985
+ F: __dxlog_file3,
986
+ L: 440,
987
+ S: this,
988
+ A: [
989
+ "this.session",
990
+ ""
991
+ ]
992
+ });
993
+ const session = this.session;
994
+ return this._pullTrackInBulk({
995
+ peerConnection: session.peerConnection,
996
+ sessionId: session.sessionId,
997
+ trackData,
998
+ ctx
999
+ });
1000
+ }
1001
+ async _closeTrackInBulk(peerConnection, mid, sessionId) {
1002
+ const transceiver = peerConnection.getTransceivers().find((t) => t.mid === mid);
1003
+ if (peerConnection.connectionState !== "connected" || transceiver === void 0) {
1004
+ return;
1005
+ }
1006
+ await this.closeTrackDispatcher.doBulkRequest({
1007
+ mid
1008
+ }, (mids) => this.taskScheduler.schedule(async () => {
1009
+ transceiver.stop();
1010
+ const activeTransceivers = peerConnection.getTransceivers().filter((t) => t.mid !== mid && t.direction !== "stopped");
1011
+ let requestBody;
1012
+ if (activeTransceivers.length > 0) {
1013
+ const offer = await peerConnection.createOffer();
1014
+ await peerConnection.setLocalDescription(offer);
1015
+ requestBody = {
1016
+ tracks: mids,
1017
+ sessionDescription: {
1018
+ sdp: peerConnection.localDescription?.sdp,
1019
+ type: "offer"
1020
+ },
1021
+ force: false
1022
+ };
1023
+ } else {
1024
+ requestBody = {
1025
+ tracks: mids,
1026
+ force: true
1027
+ };
1028
+ }
1029
+ const response = await this._fetch(`/sessions/${sessionId}/tracks/close`, {
1030
+ method: "PUT",
1031
+ body: JSON.stringify(requestBody)
1032
+ });
1033
+ if (requestBody.sessionDescription) {
1034
+ await peerConnection.setRemoteDescription(new RTCSessionDescription(response.sessionDescription));
1035
+ }
1036
+ }));
1037
+ }
1038
+ };
1039
+ var resolveTrack = async (peerConnection, compare, timeout = NETWORK_TIMEOUT) => new Promise((resolve, reject) => {
1040
+ setTimeout(reject, timeout);
1041
+ const handler = () => {
1042
+ const transceiver = peerConnection.getTransceivers().find(compare);
1043
+ if (transceiver) {
1044
+ resolve(transceiver.receiver.track);
1045
+ peerConnection.removeEventListener("track", handler);
1046
+ }
1047
+ };
1048
+ peerConnection.addEventListener("track", handler);
1049
+ });
1050
+ var peerConnectionIsConnected = async (peerConnection) => {
1051
+ if (peerConnection.connectionState !== "connected") {
1052
+ const connected = new Promise((resolve, reject) => {
1053
+ const timeout = setTimeout(() => {
1054
+ peerConnection.removeEventListener("connectionstatechange", connectionStateChangeHandler);
1055
+ reject(new Error("Connection timeout"));
1056
+ }, NETWORK_TIMEOUT);
1057
+ const connectionStateChangeHandler = () => {
1058
+ if (peerConnection.connectionState === "connected") {
1059
+ peerConnection.removeEventListener("connectionstatechange", connectionStateChangeHandler);
1060
+ clearTimeout(timeout);
1061
+ resolve(void 0);
1062
+ }
1063
+ };
1064
+ peerConnection.addEventListener("connectionstatechange", connectionStateChangeHandler);
1065
+ });
1066
+ await connected;
1067
+ }
1068
+ };
1069
+
1070
+ // src/calls/util/media.ts
1071
+ import { log as log3 } from "@dxos/log";
1072
+ var __dxlog_file4 = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/calls/util/media.ts";
1073
+ var getUserMediaTrack = async (kind, constraints = {}, deviceList) => {
1074
+ deviceList ??= (await getDeviceList()).filter((device) => device.kind === kind);
1075
+ const firstDevice = deviceList[0];
1076
+ if (!firstDevice) {
1077
+ throw new Error("No devices found");
1078
+ }
1079
+ return acquireTrack(firstDevice, constraints);
1080
+ };
1081
+ var acquireTrack = async (device, constraints) => {
1082
+ const { deviceId, label } = device;
1083
+ log3.info(`requesting ${label}`, void 0, {
1084
+ F: __dxlog_file4,
1085
+ L: 23,
1086
+ S: void 0,
1087
+ C: (f, a) => f(...a)
1088
+ });
1089
+ const mediaStream = await navigator.mediaDevices.getUserMedia(device.kind === "videoinput" ? {
1090
+ video: {
1091
+ ...constraints,
1092
+ deviceId
1093
+ }
1094
+ } : {
1095
+ audio: {
1096
+ ...constraints,
1097
+ deviceId
1098
+ }
1099
+ });
1100
+ return device.kind === "videoinput" ? mediaStream.getVideoTracks()[0] : mediaStream.getAudioTracks()[0];
1101
+ };
1102
+ var getDeviceList = () => navigator.mediaDevices.enumerateDevices();
1103
+ var SCREENSHARE_CONSTRAINTS = {
1104
+ video: {
1105
+ width: {
1106
+ max: 1920
1107
+ },
1108
+ height: {
1109
+ max: 1080
1110
+ },
1111
+ frameRate: {
1112
+ max: 10
1113
+ }
1114
+ }
1115
+ };
1116
+ var getScreenshare = async ({ contentHint }) => {
1117
+ const ms = await navigator.mediaDevices.getDisplayMedia(SCREENSHARE_CONSTRAINTS);
1118
+ ms.getVideoTracks().forEach((track) => {
1119
+ if (contentHint && "contentHint" in track) {
1120
+ track.contentHint = contentHint;
1121
+ }
1122
+ });
1123
+ return ms;
1124
+ };
1125
+
1126
+ // src/calls/util/stub-media-streams.ts
1127
+ import { scheduleTaskInterval as scheduleTaskInterval2, waitForCondition } from "@dxos/async";
1128
+ import { cancelWithContext } from "@dxos/context";
1129
+ import { invariant as invariant4 } from "@dxos/invariant";
1130
+ var __dxlog_file5 = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/calls/util/stub-media-streams.ts";
1131
+ var createBlackCanvasStreamTrack = async ({ ctx, width, height }) => {
1132
+ const canvas = document.createElement("canvas");
1133
+ canvas.width = width;
1134
+ canvas.height = height;
1135
+ const canvasCtx = canvas.getContext("2d");
1136
+ invariant4(canvasCtx, void 0, {
1137
+ F: __dxlog_file5,
1138
+ L: 28,
1139
+ S: void 0,
1140
+ A: [
1141
+ "canvasCtx",
1142
+ ""
1143
+ ]
1144
+ });
1145
+ const drawFrame = () => {
1146
+ canvasCtx.fillStyle = "black";
1147
+ canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
1148
+ };
1149
+ scheduleTaskInterval2(ctx, async () => drawFrame(), 200);
1150
+ const track = canvas.captureStream().getVideoTracks()[0];
1151
+ drawFrame();
1152
+ await cancelWithContext(ctx, waitForCondition({
1153
+ condition: () => track.readyState === "live",
1154
+ timeout: 1e3
1155
+ }));
1156
+ return track;
1157
+ };
1158
+ var audioContextStartedPreviously = false;
1159
+ var userGestureEvents = [
1160
+ "click",
1161
+ "contextmenu",
1162
+ "auxclick",
1163
+ "dblclick",
1164
+ "mousedown",
1165
+ "mouseup",
1166
+ "pointerup",
1167
+ "touchend",
1168
+ "keydown",
1169
+ "keyup"
1170
+ ];
1171
+ var createInaudibleAudioStreamTrack = async ({ ctx }) => {
1172
+ const audioContext = new window.AudioContext();
1173
+ const oscillator = audioContext.createOscillator();
1174
+ oscillator.type = "triangle";
1175
+ oscillator.frequency.setValueAtTime(20, audioContext.currentTime);
1176
+ const gainNode = audioContext.createGain();
1177
+ gainNode.gain.setValueAtTime(0, audioContext.currentTime);
1178
+ oscillator.connect(gainNode);
1179
+ const destination = audioContext.createMediaStreamDestination();
1180
+ gainNode.connect(destination);
1181
+ let oscillatorStarted = false;
1182
+ const ensureOscillatorStarted = () => {
1183
+ if (oscillatorStarted) return;
1184
+ oscillator.start();
1185
+ oscillatorStarted = true;
1186
+ };
1187
+ const stateChangeHandler = () => {
1188
+ if (audioContext.state === "running") {
1189
+ audioContextStartedPreviously = true;
1190
+ ensureOscillatorStarted();
1191
+ }
1192
+ if (audioContext.state === "suspended" || audioContext.state === "interrupted") {
1193
+ resumeAudioContext();
1194
+ }
1195
+ };
1196
+ audioContext.addEventListener("statechange", stateChangeHandler);
1197
+ const resumeAudioContext = () => {
1198
+ void audioContext.resume().then(() => {
1199
+ cleanUpUserGestureListeners();
1200
+ });
1201
+ };
1202
+ const cleanUpUserGestureListeners = () => {
1203
+ userGestureEvents.forEach((gesture) => {
1204
+ document.removeEventListener(gesture, resumeAudioContext, {
1205
+ capture: true
1206
+ });
1207
+ });
1208
+ };
1209
+ if (audioContextStartedPreviously) {
1210
+ resumeAudioContext();
1211
+ } else {
1212
+ userGestureEvents.forEach((gesture) => {
1213
+ document.addEventListener(gesture, resumeAudioContext, {
1214
+ capture: true
1215
+ });
1216
+ });
1217
+ }
1218
+ ctx.onDispose(async () => {
1219
+ cleanUpUserGestureListeners();
1220
+ oscillator.disconnect();
1221
+ oscillator.stop();
1222
+ await audioContext.close();
1223
+ });
1224
+ return destination.stream.getAudioTracks()[0];
1225
+ };
1226
+
1227
+ // src/calls/speaking-monitor.ts
1228
+ var NOT_SPEAKING_AFTER = 500;
1229
+ var START_SPEAKING_THRESHOLD = 0.05;
1230
+ var CONTINUE_SPEAKING_THRESHOLD = 0.02;
1231
+ var MIN_EVENT_INTERVAL = 100;
1232
+ var SpeakingMonitor = class extends Resource3 {
1233
+ _mediaStreamTrack;
1234
+ /**
1235
+ * Event that is emitted when the user starts or stops speaking.
1236
+ * It is debounced to prevent rapid state changes.
1237
+ */
1238
+ speakingChanged = new Event2();
1239
+ /**
1240
+ * Real state of the user speaking.
1241
+ */
1242
+ _isSpeaking = false;
1243
+ _lastEventTime = 0;
1244
+ _deferredUpdate;
1245
+ constructor(_mediaStreamTrack) {
1246
+ super(), this._mediaStreamTrack = _mediaStreamTrack;
1247
+ }
1248
+ get isSpeaking() {
1249
+ return this._isSpeaking;
1250
+ }
1251
+ async _open() {
1252
+ this._deferredUpdate = new DeferredTask2(this._ctx, async () => this._emitSpeakingChanged());
1253
+ let timeout;
1254
+ const cleanup = monitorAudioLevel({
1255
+ mediaStreamTrack: this._mediaStreamTrack,
1256
+ onMeasure: (vol) => {
1257
+ const audioLevelAboveThreshold = vol > (this._isSpeaking ? CONTINUE_SPEAKING_THRESHOLD : START_SPEAKING_THRESHOLD);
1258
+ if (audioLevelAboveThreshold) {
1259
+ clearTimeout(timeout);
1260
+ timeout = void 0;
1261
+ if (!this._isSpeaking) {
1262
+ this._isSpeaking = true;
1263
+ this._deferredUpdate?.schedule();
1264
+ }
1265
+ } else if (timeout === void 0) {
1266
+ timeout = setTimeout(() => {
1267
+ this._isSpeaking = false;
1268
+ timeout = void 0;
1269
+ this._deferredUpdate?.schedule();
1270
+ }, NOT_SPEAKING_AFTER);
1271
+ }
1272
+ }
1273
+ });
1274
+ this._ctx.onDispose(() => {
1275
+ cleanup();
1276
+ clearTimeout(timeout);
1277
+ });
1278
+ }
1279
+ /**
1280
+ * Emits the speaking changed event with debouncing based on timing.
1281
+ */
1282
+ async _emitSpeakingChanged() {
1283
+ const timeSinceLastEvent = Date.now() - this._lastEventTime;
1284
+ const timeToNextEvent = MIN_EVENT_INTERVAL - timeSinceLastEvent;
1285
+ if (timeToNextEvent > 0) {
1286
+ await sleep(timeToNextEvent);
1287
+ }
1288
+ this._lastEventTime = Date.now();
1289
+ this.speakingChanged.emit(this._isSpeaking);
1290
+ }
1291
+ };
1292
+
1293
+ // src/calls/media-manager.ts
1294
+ function _ts_decorate2(decorators, target, key, desc) {
1295
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1296
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1297
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1298
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1299
+ }
1300
+ var __dxlog_file6 = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/calls/media-manager.ts";
1301
+ var VIDEO_WIDTH = 1280;
1302
+ var VIDEO_HEIGHT = 720;
1303
+ var MAX_WEB_CAM_FRAMERATE = 24;
1304
+ var MAX_WEB_CAM_BITRATE = 12e5;
1305
+ var RETRY_INTERVAL = 100;
1306
+ var USE_INAUDIBLE_AUDIO = true;
1307
+ var MediaManager = class extends Resource4 {
1308
+ stateUpdated = new Event3();
1309
+ _state = {
1310
+ pulledVideoStreams: {},
1311
+ pulledAudioTracks: {}
1312
+ };
1313
+ _speakingMonitor = void 0;
1314
+ _trackToReconcile = [];
1315
+ _blackCanvasStreamTrack = void 0;
1316
+ _inaudibleAudioStreamTrack = void 0;
1317
+ _pushTracksTask = void 0;
1318
+ _pullTracksTask = void 0;
1319
+ get isSpeaking() {
1320
+ return this._speakingMonitor?.isSpeaking;
1321
+ }
1322
+ /**
1323
+ * @internal
1324
+ */
1325
+ _getState() {
1326
+ return this._state;
1327
+ }
1328
+ async _open() {
1329
+ this._blackCanvasStreamTrack = await createBlackCanvasStreamTrack({
1330
+ ctx: this._ctx,
1331
+ width: VIDEO_WIDTH,
1332
+ height: VIDEO_HEIGHT
1333
+ });
1334
+ this._state.videoTrack = this._blackCanvasStreamTrack;
1335
+ this._state.videoStream = new MediaStream();
1336
+ this._state.videoStream.addTrack(this._state.videoTrack);
1337
+ if (USE_INAUDIBLE_AUDIO) {
1338
+ this._inaudibleAudioStreamTrack = await createInaudibleAudioStreamTrack({
1339
+ ctx: this._ctx
1340
+ });
1341
+ this._state.audioTrack = this._inaudibleAudioStreamTrack;
1342
+ }
1343
+ this._pushTracksTask = new DeferredTask3(this._ctx, async () => {
1344
+ await this._pushTracks();
1345
+ });
1346
+ this._pullTracksTask = new DeferredTask3(this._ctx, async () => {
1347
+ await this._reconcilePulledMedia();
1348
+ });
1349
+ }
1350
+ async _close() {
1351
+ void this._speakingMonitor?.close();
1352
+ this._state.videoTrack && this._state.videoStream?.removeTrack(this._state.videoTrack);
1353
+ this._state.audioTrack?.stop();
1354
+ this._state.videoTrack?.stop();
1355
+ this._state.screenshareTrack?.stop();
1356
+ this._pushTracksTask = void 0;
1357
+ this._pullTracksTask = void 0;
1358
+ }
1359
+ async join(serviceConfig) {
1360
+ this._state.peer = new CallsServicePeer(serviceConfig);
1361
+ await this._state.peer.open();
1362
+ this._pushTracksTask.schedule();
1363
+ }
1364
+ async leave() {
1365
+ await Promise.all(Object.values(this._state.pulledAudioTracks).map(({ ctx }) => ctx.dispose()));
1366
+ await Promise.all(Object.values(this._state.pulledVideoStreams).map(({ ctx }) => ctx.dispose()));
1367
+ this._trackToReconcile = [];
1368
+ await this._state.peer?.close();
1369
+ this._state.peer = void 0;
1370
+ this._state.pushedVideoTrack = void 0;
1371
+ this._state.pushedAudioTrack = void 0;
1372
+ this._state.pushedScreenshareTrack = void 0;
1373
+ this._state.pulledAudioTracks = {};
1374
+ this._state.pulledVideoStreams = {};
1375
+ }
1376
+ async turnVideoOn() {
1377
+ this._state.videoStream.removeTrack(this._state.videoTrack);
1378
+ this._state.videoTrack = await getUserMediaTrack("videoinput", {
1379
+ width: VIDEO_WIDTH,
1380
+ height: VIDEO_HEIGHT
1381
+ });
1382
+ this._state.videoStream.addTrack(this._state.videoTrack);
1383
+ this._state.videoEnabled = true;
1384
+ this.stateUpdated.emit(this._state);
1385
+ this._pushTracksTask.schedule();
1386
+ }
1387
+ async turnVideoOff() {
1388
+ if (this._state.videoTrack !== this._blackCanvasStreamTrack) {
1389
+ this._state.videoStream.removeTrack(this._state.videoTrack);
1390
+ this._state.videoTrack?.stop();
1391
+ this._state.videoTrack = this._blackCanvasStreamTrack;
1392
+ this._state.videoStream.addTrack(this._state.videoTrack);
1393
+ }
1394
+ this._state.videoEnabled = false;
1395
+ this.stateUpdated.emit(this._state);
1396
+ this._pushTracksTask.schedule();
1397
+ }
1398
+ // TODO(mykola): Change to `setAudioEnabled(enabled: boolean)`.
1399
+ async turnAudioOn() {
1400
+ void this._speakingMonitor?.close();
1401
+ this._state.audioEnabled = true;
1402
+ this._state.audioTrack = await getUserMediaTrack("audioinput", {
1403
+ echoCancellation: true,
1404
+ noiseSuppression: true,
1405
+ autoGainControl: true,
1406
+ sampleRate: 16e3
1407
+ });
1408
+ this.stateUpdated.emit(this._state);
1409
+ this._pushTracksTask.schedule();
1410
+ this._speakingMonitor = new SpeakingMonitor(this._state.audioTrack);
1411
+ this._speakingMonitor.speakingChanged.on(this._ctx, () => this.stateUpdated.emit(this._state));
1412
+ void this._speakingMonitor.open();
1413
+ }
1414
+ async turnAudioOff() {
1415
+ void this._speakingMonitor?.close();
1416
+ this._speakingMonitor = void 0;
1417
+ this._state.audioEnabled = false;
1418
+ if (USE_INAUDIBLE_AUDIO && this._state.audioTrack !== this._inaudibleAudioStreamTrack) {
1419
+ this._state.audioTrack?.stop();
1420
+ this._state.audioTrack = this._inaudibleAudioStreamTrack;
1421
+ } else {
1422
+ this._state.audioTrack?.stop();
1423
+ this._state.audioTrack = void 0;
1424
+ }
1425
+ this.stateUpdated.emit(this._state);
1426
+ this._pushTracksTask.schedule();
1427
+ }
1428
+ async turnScreenshareOn() {
1429
+ const ms = await getScreenshare({
1430
+ contentHint: "text"
1431
+ });
1432
+ this._state.screenshareVideoStream = ms;
1433
+ this._state.screenshareTrack = ms.getVideoTracks()[0];
1434
+ this._state.screenshareEnabled = true;
1435
+ this.stateUpdated.emit(this._state);
1436
+ this._pushTracksTask.schedule();
1437
+ }
1438
+ async turnScreenshareOff() {
1439
+ this._state.screenshareEnabled = false;
1440
+ this._state.screenshareTrack?.stop();
1441
+ this._state.screenshareTrack = void 0;
1442
+ this.stateUpdated.emit(this._state);
1443
+ this._pushTracksTask.schedule();
1444
+ }
1445
+ /**
1446
+ * @internal
1447
+ */
1448
+ _schedulePullTracks(tracks) {
1449
+ if (!tracks || this._trackToReconcile.every((name) => tracks.includes(name)) && this._trackToReconcile.length === tracks.length) {
1450
+ return;
1451
+ }
1452
+ this._trackToReconcile = tracks;
1453
+ this._pullTracksTask.schedule();
1454
+ }
1455
+ async _reconcilePulledMedia() {
1456
+ log4("reconciling tracks", void 0, {
1457
+ F: __dxlog_file6,
1458
+ L: 229,
1459
+ S: this,
1460
+ C: (f, a) => f(...a)
1461
+ });
1462
+ await cancelWithContext2(this._ctx, sleep2(800));
1463
+ const trackNames = this._trackToReconcile;
1464
+ const tracksToPull = trackNames.filter((name) => !this._state.pulledAudioTracks[name] && !this._state.pulledVideoStreams[name]);
1465
+ const audioTracksToClose = Object.entries(this._state.pulledAudioTracks).filter(([key]) => !trackNames.some((name) => name === key));
1466
+ const videoStreamsToClose = Object.entries(this._state.pulledVideoStreams).filter(([key]) => !trackNames.some((name) => name === key));
1467
+ log4("reconciling tracks", {
1468
+ trackNames,
1469
+ tracksToPull,
1470
+ videoStreamsToClose,
1471
+ audioTracksToClose,
1472
+ currentAudioTracks: Object.keys(this._state.pulledAudioTracks),
1473
+ currentVideoStreams: Object.keys(this._state.pulledVideoStreams)
1474
+ }, {
1475
+ F: __dxlog_file6,
1476
+ L: 247,
1477
+ S: this,
1478
+ C: (f, a) => f(...a)
1479
+ });
1480
+ const pullResults = await Promise.all(tracksToPull.map((name) => this._pullTrack(name)));
1481
+ await Promise.all([
1482
+ ...audioTracksToClose,
1483
+ ...videoStreamsToClose
1484
+ ].map(([_, { ctx }]) => ctx.dispose()));
1485
+ log4("reconciled tracks", {
1486
+ currentAudioTracks: Object.keys(this._state.pulledAudioTracks),
1487
+ currentVideoStreams: Object.keys(this._state.pulledVideoStreams)
1488
+ }, {
1489
+ F: __dxlog_file6,
1490
+ L: 262,
1491
+ S: this,
1492
+ C: (f, a) => f(...a)
1493
+ });
1494
+ this.stateUpdated.emit(this._state);
1495
+ if (pullResults.some(({ shouldRetry }) => shouldRetry)) {
1496
+ await cancelWithContext2(this._ctx, sleep2(RETRY_INTERVAL));
1497
+ log4.info("retrying pull tracks", {
1498
+ tracksToPull
1499
+ }, {
1500
+ F: __dxlog_file6,
1501
+ L: 270,
1502
+ S: this,
1503
+ C: (f, a) => f(...a)
1504
+ });
1505
+ invariant5(this._pullTracksTask, void 0, {
1506
+ F: __dxlog_file6,
1507
+ L: 271,
1508
+ S: this,
1509
+ A: [
1510
+ "this._pullTracksTask",
1511
+ ""
1512
+ ]
1513
+ });
1514
+ this._pullTracksTask.schedule();
1515
+ }
1516
+ }
1517
+ async _pushTracks() {
1518
+ if (!this._state.peer?.isOpen) {
1519
+ return;
1520
+ }
1521
+ let updated = false;
1522
+ const [pushVideoResult, pushAudioResult, pushScreenshareResult] = await Promise.all([
1523
+ this._maybePushTrack(this._state.videoTrack, this._state.pushedVideoTrack, [
1524
+ {
1525
+ maxFramerate: MAX_WEB_CAM_FRAMERATE,
1526
+ maxBitrate: MAX_WEB_CAM_BITRATE
1527
+ }
1528
+ ]),
1529
+ this._maybePushTrack(this._state.audioTrack, this._state.pushedAudioTrack, [
1530
+ {
1531
+ networkPriority: "high"
1532
+ }
1533
+ ]),
1534
+ this._maybePushTrack(this._state.screenshareTrack, this._state.pushedScreenshareTrack)
1535
+ ]);
1536
+ if (pushVideoResult.track !== this._state.pushedVideoTrack) {
1537
+ this._state.pushedVideoTrack = pushVideoResult.track;
1538
+ updated = true;
1539
+ }
1540
+ if (pushAudioResult.track !== this._state.pushedAudioTrack) {
1541
+ this._state.pushedAudioTrack = pushAudioResult.track;
1542
+ updated = true;
1543
+ }
1544
+ if (pushScreenshareResult.track !== this._state.pushedScreenshareTrack) {
1545
+ this._state.pushedScreenshareTrack = pushScreenshareResult.track;
1546
+ updated = true;
1547
+ }
1548
+ const shouldRetry = pushVideoResult.shouldRetry || pushAudioResult.shouldRetry || pushScreenshareResult.shouldRetry;
1549
+ if (updated) {
1550
+ this.stateUpdated.emit(this._state);
1551
+ }
1552
+ if (shouldRetry) {
1553
+ await cancelWithContext2(this._ctx, sleep2(RETRY_INTERVAL));
1554
+ log4.info("retrying push tracks", {
1555
+ pushVideoResult,
1556
+ pushAudioResult,
1557
+ pushScreenshareResult
1558
+ }, {
1559
+ F: __dxlog_file6,
1560
+ L: 310,
1561
+ S: this,
1562
+ C: (f, a) => f(...a)
1563
+ });
1564
+ invariant5(this._pushTracksTask, void 0, {
1565
+ F: __dxlog_file6,
1566
+ L: 311,
1567
+ S: this,
1568
+ A: [
1569
+ "this._pushTracksTask",
1570
+ ""
1571
+ ]
1572
+ });
1573
+ this._pushTracksTask.schedule();
1574
+ }
1575
+ }
1576
+ async _pullTrack(name) {
1577
+ const ctx = this._ctx.derive();
1578
+ try {
1579
+ const trackData = TrackNameCodec.decode(name);
1580
+ const track = await this._state.peer.pullTrack({
1581
+ trackData: {
1582
+ ...trackData,
1583
+ mid: void 0
1584
+ },
1585
+ ctx
1586
+ });
1587
+ if (track?.readyState === "ended") {
1588
+ throw new Error("Pulled track ended immediately");
1589
+ }
1590
+ switch (track?.kind) {
1591
+ case "audio": {
1592
+ this._state.pulledAudioTracks[name] = {
1593
+ track,
1594
+ ctx
1595
+ };
1596
+ ctx.onDispose(() => delete this._state.pulledAudioTracks[name]);
1597
+ return {
1598
+ shouldRetry: false
1599
+ };
1600
+ }
1601
+ case "video": {
1602
+ const mediaStream = new MediaStream();
1603
+ mediaStream.addTrack(track);
1604
+ this._state.pulledVideoStreams[name] = {
1605
+ stream: mediaStream,
1606
+ ctx
1607
+ };
1608
+ ctx.onDispose(() => {
1609
+ mediaStream.removeTrack(track);
1610
+ track.stop();
1611
+ delete this._state.pulledVideoStreams[name];
1612
+ });
1613
+ return {
1614
+ shouldRetry: false
1615
+ };
1616
+ }
1617
+ default:
1618
+ throw new Error(`Invalid track kind: ${track?.kind}`);
1619
+ }
1620
+ } catch (err) {
1621
+ log4.info("failed to pull track", {
1622
+ err,
1623
+ name
1624
+ }, {
1625
+ F: __dxlog_file6,
1626
+ L: 347,
1627
+ S: this,
1628
+ C: (f, a) => f(...a)
1629
+ });
1630
+ void ctx.dispose();
1631
+ return {
1632
+ shouldRetry: true
1633
+ };
1634
+ }
1635
+ }
1636
+ async _maybePushTrack(track, previousTrack, encodings) {
1637
+ if (!track && !previousTrack) {
1638
+ return {
1639
+ track: void 0
1640
+ };
1641
+ }
1642
+ const ctx = this._ctx.derive();
1643
+ try {
1644
+ return {
1645
+ track: await this._state.peer.pushTrack({
1646
+ ctx,
1647
+ track: track ?? null,
1648
+ previousTrack,
1649
+ encodings
1650
+ })
1651
+ };
1652
+ } catch (err) {
1653
+ log4.info("failed to push track", {
1654
+ err,
1655
+ track,
1656
+ previousTrack,
1657
+ encodings
1658
+ }, {
1659
+ F: __dxlog_file6,
1660
+ L: 373,
1661
+ S: this,
1662
+ C: (f, a) => f(...a)
1663
+ });
1664
+ void ctx.dispose();
1665
+ return {
1666
+ shouldRetry: true
1667
+ };
1668
+ }
1669
+ }
1670
+ };
1671
+ _ts_decorate2([
1672
+ synchronized2
1673
+ ], MediaManager.prototype, "join", null);
1674
+ _ts_decorate2([
1675
+ synchronized2
1676
+ ], MediaManager.prototype, "leave", null);
1677
+
1678
+ // src/calls/call-manager.ts
1679
+ function _ts_decorate3(decorators, target, key, desc) {
1680
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1681
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1682
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1683
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1684
+ }
1685
+ var __dxlog_file7 = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/calls/call-manager.ts";
1686
+ var CallManager = class extends Resource5 {
1687
+ _client;
1688
+ _registry;
1689
+ callStateUpdated = new Event4();
1690
+ // TODO(wittjosiah): Consolidate isSpeaking into the MediaState type.
1691
+ mediaStateUpdated = new Event4();
1692
+ left = new Event4();
1693
+ /**
1694
+ * Atom-based state. Updated via `_updateState()`.
1695
+ * CAUTION: Do not change directly.
1696
+ */
1697
+ _stateAtom = Atom.make({
1698
+ call: {},
1699
+ media: {
1700
+ pulledAudioTracks: {},
1701
+ pulledVideoStreams: {}
1702
+ }
1703
+ });
1704
+ // Derived atoms for reactive subscriptions.
1705
+ _roomIdAtom = Atom.make((get) => get(this._stateAtom).call.roomId);
1706
+ _raisedHandAtom = Atom.make((get) => get(this._stateAtom).call.raisedHand ?? false);
1707
+ _speakingAtom = Atom.make((get) => get(this._stateAtom).call.speaking ?? false);
1708
+ _joinedAtom = Atom.make((get) => get(this._stateAtom).call.joined ?? false);
1709
+ _selfAtom = Atom.make((get) => get(this._stateAtom).call.self ?? {});
1710
+ _tracksAtom = Atom.make((get) => get(this._stateAtom).call.tracks ?? {});
1711
+ _usersAtom = Atom.make((get) => get(this._stateAtom).call.users ?? []);
1712
+ _mediaAtom = Atom.make((get) => get(this._stateAtom).media);
1713
+ _audioTracksToPlayAtom = Atom.make((get) => {
1714
+ const state = get(this._stateAtom);
1715
+ return (state.call.users ?? []).map((user) => user.tracks?.audioEnabled ? user.tracks?.audio : void 0).filter(isNonNullable2).map((track) => state.media.pulledAudioTracks[track]?.track).filter(isNonNullable2);
1716
+ });
1717
+ _videoStreamAtomFamily = Atom.family((name) => Atom.make((get) => get(this._stateAtom).media.pulledVideoStreams[name]?.stream));
1718
+ _activityAtomFamily = Atom.family((key) => Atom.make((get) => get(this._stateAtom).call.activities?.[key]));
1719
+ _swarmSynchronizer;
1720
+ _mediaManager;
1721
+ //
1722
+ // Derived atoms for reactive UI subscriptions.
1723
+ //
1724
+ /** Derived atom for roomId. */
1725
+ get roomIdAtom() {
1726
+ return this._roomIdAtom;
1727
+ }
1728
+ /** Derived atom for raisedHand. */
1729
+ get raisedHandAtom() {
1730
+ return this._raisedHandAtom;
1731
+ }
1732
+ /** Derived atom for speaking. */
1733
+ get speakingAtom() {
1734
+ return this._speakingAtom;
1735
+ }
1736
+ /** Derived atom for joined. */
1737
+ get joinedAtom() {
1738
+ return this._joinedAtom;
1739
+ }
1740
+ /** Derived atom for self. */
1741
+ get selfAtom() {
1742
+ return this._selfAtom;
1743
+ }
1744
+ /** Derived atom for tracks. */
1745
+ get tracksAtom() {
1746
+ return this._tracksAtom;
1747
+ }
1748
+ /** Derived atom for users. */
1749
+ get usersAtom() {
1750
+ return this._usersAtom;
1751
+ }
1752
+ /** Derived atom for media. */
1753
+ get mediaAtom() {
1754
+ return this._mediaAtom;
1755
+ }
1756
+ /** Derived atom for audioTracksToPlay. */
1757
+ get audioTracksToPlayAtom() {
1758
+ return this._audioTracksToPlayAtom;
1759
+ }
1760
+ /** Returns the full state atom for reactive subscriptions. */
1761
+ get stateAtom() {
1762
+ return this._stateAtom;
1763
+ }
1764
+ /** Returns a derived atom for a video stream by name. */
1765
+ videoStreamAtom(name) {
1766
+ return this._videoStreamAtomFamily(name);
1767
+ }
1768
+ /** Returns a derived atom for an activity by key. */
1769
+ activityAtom(key) {
1770
+ return this._activityAtomFamily(key);
1771
+ }
1772
+ setRoomId(roomId) {
1773
+ this._swarmSynchronizer._setRoomId(roomId);
1774
+ }
1775
+ setSpeaking(speaking) {
1776
+ this._swarmSynchronizer.setSpeaking(speaking);
1777
+ }
1778
+ setRaisedHand(raisedHand) {
1779
+ this._swarmSynchronizer.setRaisedHand(raisedHand);
1780
+ }
1781
+ setActivity(key, payload) {
1782
+ this._swarmSynchronizer.setActivity(key, payload);
1783
+ }
1784
+ turnAudioOn() {
1785
+ return this._mediaManager.turnAudioOn();
1786
+ }
1787
+ turnAudioOff() {
1788
+ return this._mediaManager.turnAudioOff();
1789
+ }
1790
+ turnVideoOn() {
1791
+ return this._mediaManager.turnVideoOn();
1792
+ }
1793
+ turnVideoOff() {
1794
+ return this._mediaManager.turnVideoOff();
1795
+ }
1796
+ turnScreenshareOn() {
1797
+ return this._mediaManager.turnScreenshareOn();
1798
+ }
1799
+ turnScreenshareOff() {
1800
+ return this._mediaManager.turnScreenshareOff();
1801
+ }
1802
+ // TODO(burdon): Can this be mocked?
1803
+ constructor(_client, _registry) {
1804
+ super(), this._client = _client, this._registry = _registry;
1805
+ this._client.config.getOrThrow("runtime.services.edge.url");
1806
+ const networkService = this._client.services.services.NetworkService;
1807
+ invariant6(networkService, "network service not found", {
1808
+ F: __dxlog_file7,
1809
+ L: 180,
1810
+ S: this,
1811
+ A: [
1812
+ "networkService",
1813
+ "'network service not found'"
1814
+ ]
1815
+ });
1816
+ this._swarmSynchronizer = new CallSwarmSynchronizer({
1817
+ networkService
1818
+ });
1819
+ this._mediaManager = new MediaManager();
1820
+ }
1821
+ async _open() {
1822
+ await this._mediaManager.open();
1823
+ await this._swarmSynchronizer.open();
1824
+ const subscription = this._client.halo.identity.subscribe((identity) => {
1825
+ if (identity) {
1826
+ this._swarmSynchronizer._setIdentity(identity);
1827
+ }
1828
+ if (this._client.halo.device) {
1829
+ this._swarmSynchronizer._setDevice(this._client.halo.device);
1830
+ }
1831
+ });
1832
+ this._ctx.onDispose(() => subscription.unsubscribe());
1833
+ this._swarmSynchronizer.stateUpdated.on(this._ctx, (state) => this._onCallStateUpdated(state));
1834
+ this._mediaManager.stateUpdated.on(this._ctx, (state) => this._onMediaStateUpdated(state));
1835
+ }
1836
+ async _close() {
1837
+ await this._swarmSynchronizer.leave();
1838
+ await this._swarmSynchronizer.close();
1839
+ await this._mediaManager.close();
1840
+ }
1841
+ async peek(roomId) {
1842
+ const peers = await this._swarmSynchronizer.querySwarm(roomId);
1843
+ return peers.length;
1844
+ }
1845
+ // TODO(mykola): Reconcile with _swarmSynchronizer.state.joined.
1846
+ async join() {
1847
+ this._swarmSynchronizer.setJoined(true);
1848
+ await this._swarmSynchronizer.join();
1849
+ await this._mediaManager.join({
1850
+ iceServers: this._client.config.get("runtime.services.ice"),
1851
+ apiBase: `${CALLS_URL}/api/calls`
1852
+ });
1853
+ }
1854
+ async leave() {
1855
+ this._swarmSynchronizer.setJoined(false);
1856
+ await this._swarmSynchronizer.leave();
1857
+ await this._mediaManager.leave();
1858
+ const roomId = this._registry.get(this._roomIdAtom);
1859
+ roomId && this.left.emit(roomId);
1860
+ }
1861
+ _onCallStateUpdated(state) {
1862
+ const tracksToPull = state.users?.filter((user) => user.joined && user.id !== state.self.id)?.flatMap((user) => [
1863
+ user.tracks?.video,
1864
+ user.tracks?.audio,
1865
+ user.tracks?.screenshare
1866
+ ]).filter(isNonNullable2);
1867
+ this._mediaManager._schedulePullTracks(tracksToPull);
1868
+ this.callStateUpdated.emit(state);
1869
+ this._updateState();
1870
+ }
1871
+ _onMediaStateUpdated(state) {
1872
+ this._swarmSynchronizer.setTracks({
1873
+ video: state.pushedVideoTrack ? TrackNameCodec.encode(state.pushedVideoTrack) : void 0,
1874
+ audio: state.pushedAudioTrack ? TrackNameCodec.encode(state.pushedAudioTrack) : void 0,
1875
+ screenshare: state.pushedScreenshareTrack ? TrackNameCodec.encode(state.pushedScreenshareTrack) : void 0,
1876
+ videoEnabled: state.videoEnabled,
1877
+ audioEnabled: state.audioEnabled,
1878
+ screenshareEnabled: state.screenshareEnabled
1879
+ });
1880
+ const isSpeaking = this._mediaManager.isSpeaking ?? false;
1881
+ this._swarmSynchronizer.setSpeaking(isSpeaking);
1882
+ this.mediaStateUpdated.emit([
1883
+ state,
1884
+ isSpeaking
1885
+ ]);
1886
+ this._updateState();
1887
+ }
1888
+ /**
1889
+ * Only this method is allowed to change state.
1890
+ */
1891
+ _updateState() {
1892
+ this._registry.set(this._stateAtom, {
1893
+ call: this._swarmSynchronizer._getState(),
1894
+ media: this._mediaManager._getState()
1895
+ });
1896
+ }
1897
+ };
1898
+ _ts_decorate3([
1899
+ synchronized3
1900
+ ], CallManager.prototype, "join", null);
1901
+ _ts_decorate3([
1902
+ synchronized3
1903
+ ], CallManager.prototype, "leave", null);
1904
+
1905
+ // src/hooks/analytics.ts
1906
+ import { useCallback } from "react";
1907
+ import { useOperationInvoker } from "@dxos/app-framework/ui";
1908
+ import { Obj } from "@dxos/echo";
1909
+ import { ObservabilityOperation } from "@dxos/plugin-observability/operations";
1910
+ import { useOnTransition } from "@dxos/react-ui";
1911
+ var useOnEditAnalytics = (message, textBlock, editing) => {
1912
+ const { invokePromise } = useOperationInvoker();
1913
+ const onEdit = useCallback(() => {
1914
+ if (!message || !textBlock) {
1915
+ return;
1916
+ }
1917
+ const db = Obj.getDatabase(message);
1918
+ if (!db) {
1919
+ return;
1920
+ }
1921
+ void invokePromise(ObservabilityOperation.SendEvent, {
1922
+ name: "threads.message.update",
1923
+ properties: {
1924
+ spaceId: db.spaceId,
1925
+ messageId: message.id,
1926
+ messageLength: textBlock?.text.length
1927
+ }
1928
+ });
1929
+ }, [
1930
+ invokePromise,
1931
+ message,
1932
+ textBlock
1933
+ ]);
1934
+ useOnTransition(editing, true, false, onEdit);
1935
+ };
1936
+
1937
+ // src/hooks/useBlackCanvasStreamTrack.tsx
1938
+ import { useEffect, useState } from "react";
1939
+ import { scheduleTask as scheduleTask2 } from "@dxos/async";
1940
+ import { Context as Context2 } from "@dxos/context";
1941
+ var __dxlog_file8 = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/hooks/useBlackCanvasStreamTrack.tsx";
1942
+ var useBlackCanvasStreamTrack = () => {
1943
+ const [blackCanvasStreamTrack, setBlackCanvasStreamTrack] = useState(void 0);
1944
+ useEffect(() => {
1945
+ const ctx = new Context2(void 0, {
1946
+ F: __dxlog_file8,
1947
+ L: 15
1948
+ });
1949
+ scheduleTask2(ctx, async () => {
1950
+ const blackCanvasStreamTrack2 = await createBlackCanvasStreamTrack({
1951
+ ctx,
1952
+ width: 720,
1953
+ height: 480
1954
+ });
1955
+ setBlackCanvasStreamTrack(blackCanvasStreamTrack2);
1956
+ });
1957
+ return () => {
1958
+ void ctx.dispose();
1959
+ };
1960
+ }, []);
1961
+ return blackCanvasStreamTrack;
1962
+ };
1963
+
1964
+ // src/hooks/useDebugMode.ts
1965
+ import { useEffect as useEffect2, useState as useState2 } from "react";
1966
+ var useDebugMode = () => {
1967
+ const [enabled, setEnabled] = useState2(false);
1968
+ useEffect2(() => {
1969
+ const handler = (ev) => {
1970
+ if (ev.key.toLowerCase() === "d" && ev.ctrlKey) {
1971
+ ev.preventDefault();
1972
+ setEnabled(!enabled);
1973
+ }
1974
+ };
1975
+ document.addEventListener("keypress", handler);
1976
+ return () => {
1977
+ document.removeEventListener("keypress", handler);
1978
+ };
1979
+ }, [
1980
+ enabled
1981
+ ]);
1982
+ return enabled;
1983
+ };
1984
+
1985
+ // src/hooks/useInaudibleAudioStreamTrack.tsx
1986
+ import { useEffect as useEffect3, useState as useState3 } from "react";
1987
+ import { scheduleTask as scheduleTask3 } from "@dxos/async";
1988
+ import { Context as Context3 } from "@dxos/context";
1989
+ var __dxlog_file9 = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/hooks/useInaudibleAudioStreamTrack.tsx";
1990
+ var useInaudibleAudioStreamTrack = () => {
1991
+ const [audioStreamTrack, setAudioStreamTrack] = useState3(void 0);
1992
+ useEffect3(() => {
1993
+ const ctx = new Context3(void 0, {
1994
+ F: __dxlog_file9,
1995
+ L: 15
1996
+ });
1997
+ scheduleTask3(ctx, async () => {
1998
+ const audioStreamTrack2 = await createInaudibleAudioStreamTrack({
1999
+ ctx
2000
+ });
2001
+ setAudioStreamTrack(audioStreamTrack2);
2002
+ });
2003
+ return () => {
2004
+ void ctx.dispose();
2005
+ };
2006
+ }, []);
2007
+ return audioStreamTrack;
2008
+ };
2009
+
2010
+ // src/hooks/useStatus.ts
2011
+ import { useEffect as useEffect4, useState as useState4 } from "react";
2012
+ var useStatus = (space, channel) => {
2013
+ const [processing, setProcessing] = useState4(false);
2014
+ useEffect4(() => {
2015
+ if (!space || !channel) {
2016
+ return;
2017
+ }
2018
+ const unsubscribe = space.listen(`status/${channel}`, (status) => {
2019
+ const { event } = status.payload ?? {};
2020
+ setProcessing(event === "processing");
2021
+ });
2022
+ const t = setInterval(() => {
2023
+ setProcessing((prev) => {
2024
+ if (typeof prev?.ts === "number" && Date.now() - prev.ts > 3e4) {
2025
+ return void 0;
2026
+ } else {
2027
+ return prev;
2028
+ }
2029
+ });
2030
+ }, 1e3);
2031
+ return () => {
2032
+ unsubscribe();
2033
+ clearInterval(t);
2034
+ };
2035
+ }, [
2036
+ space,
2037
+ channel
2038
+ ]);
2039
+ return processing;
2040
+ };
2041
+
2042
+ // src/hooks/useVideoStreamTrack.tsx
2043
+ import { useEffect as useEffect5, useRef, useState as useState5 } from "react";
2044
+ var useVideoStreamTrack = (videoElement, videoSrc) => {
2045
+ const [videoStreamTrack, setVideoStreamTrack] = useState5(void 0);
2046
+ const hadRun = useRef(false);
2047
+ useEffect5(() => {
2048
+ if (!videoElement.current || hadRun.current || !videoSrc) {
2049
+ return;
2050
+ }
2051
+ hadRun.current = true;
2052
+ videoElement.current.addEventListener("playing", () => {
2053
+ if (videoStreamTrack) {
2054
+ return;
2055
+ }
2056
+ const stream = videoElement.current.captureStream();
2057
+ const track = stream.getTracks()[0];
2058
+ if (track && !videoStreamTrack) {
2059
+ setVideoStreamTrack(track);
2060
+ }
2061
+ stream.onaddtrack = (event) => {
2062
+ if (event.track.kind === "video" && !videoStreamTrack) {
2063
+ setVideoStreamTrack(event.track);
2064
+ }
2065
+ };
2066
+ });
2067
+ videoElement.current.src = videoSrc;
2068
+ }, [
2069
+ videoElement.current,
2070
+ videoSrc
2071
+ ]);
2072
+ return videoStreamTrack;
2073
+ };
2074
+
2075
+ // src/meta.ts
2076
+ import { trim } from "@dxos/util";
2077
+ var meta = {
2078
+ id: "org.dxos.plugin.thread",
2079
+ name: "Chat",
2080
+ description: trim`
2081
+ Multi-modal communication platform supporting text chat, voice, and video conferencing.
2082
+ Create threaded conversations and add contextual comments directly on any workspace object.
2083
+ `,
2084
+ icon: "ph--video-conference--regular",
2085
+ iconHue: "rose",
2086
+ source: "https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-thread"
2087
+ };
2088
+ var THREAD_ITEM = `${meta.id}.item`;
2089
+
2090
+ // src/ThreadPlugin.tsx
2091
+ import * as Effect from "effect/Effect";
2092
+ import * as Option from "effect/Option";
2093
+ import { Capability, Plugin } from "@dxos/app-framework";
2094
+ import { AppActivationEvents, AppPlugin } from "@dxos/app-toolkit";
2095
+ import { Annotation, Ref, Type as Type2 } from "@dxos/echo";
2096
+ import { Operation } from "@dxos/operation";
2097
+ import { ClientEvents } from "@dxos/plugin-client/types";
2098
+ import { MarkdownEvents } from "@dxos/plugin-markdown";
2099
+ import { SpaceOperation } from "@dxos/plugin-space/operations";
2100
+ import { SpaceCapabilities, SpaceEvents } from "@dxos/plugin-space/types";
2101
+ import { translations as threadTranslations } from "@dxos/react-ui-thread";
2102
+ import { AnchoredTo, Message, Thread } from "@dxos/types";
2103
+ import { AppGraphBuilder, BlueprintDefinition, CallManager as CallManager2, Markdown, OperationHandler, UndoMappings, ReactRoot, ReactSurface, ThreadState } from "#capabilities";
2104
+ import { THREAD_ITEM as THREAD_ITEM2, meta as meta3 } from "#meta";
2105
+ import { ThreadOperation } from "#operations";
2106
+ import { Channel as Channel2 } from "#types";
87
2107
 
88
2108
  // src/translations.ts
89
2109
  import { Type } from "@dxos/echo";
2110
+ import { meta as meta2 } from "#meta";
2111
+ import { Channel } from "#types";
90
2112
  var translations = [
91
2113
  {
92
2114
  "en-US": {
93
- [Type.getTypename(Channel_exports.Channel)]: {
94
- "typename label": "Channel",
95
- "typename label_zero": "Channels",
96
- "typename label_one": "Channel",
97
- "typename label_other": "Channels",
98
- "object name placeholder": "New channel",
99
- "rename object label": "Rename channel",
100
- "delete object label": "Delete channel",
101
- "object deleted label": "Channel deleted"
2115
+ [Type.getTypename(Channel.Channel)]: {
2116
+ "typename.label": "Channel",
2117
+ "typename.label_zero": "Channels",
2118
+ "typename.label_one": "Channel",
2119
+ "typename.label_other": "Channels",
2120
+ "object-name.placeholder": "New channel",
2121
+ "add-object.label": "Add channel",
2122
+ "rename-object.label": "Rename channel",
2123
+ "delete-object.label": "Delete channel",
2124
+ "object-deleted.label": "Channel deleted"
102
2125
  },
103
- [meta.id]: {
104
- "plugin name": "Chat",
105
- "channel title label": "Title",
106
- "message placeholder": "Reply\u2026",
107
- "activity message": "Processing\u2026",
108
- "anonymous label": "Anonymous",
109
- "delete message block label": "Delete message block",
110
- "detached thread label": "Referenced content was removed",
111
- "delete thread label": "Delete thread",
112
- "resolve thread label": "Resolve thread",
113
- "thread deleted label": "Thread deleted",
114
- "message deleted label": "Message deleted",
115
- "comments heading": "Comments",
116
- "chat heading": "Chat",
117
- "draft button": "DRAFT",
118
- "no comments title": "Comments",
119
- "no comments message": "Click on the <commentIcon></commentIcon> button in the document toolbar to create a comment thread on the selected text.",
120
- "toggle show resolved": "Show resolved",
121
- "unnamed object threads label": "Threads",
122
- "mark as resolved label": "Mark as resolved",
123
- "mark as unresolved label": "Mark as unresolved",
124
- "save message label": "Save",
125
- "edit message label": "Edit",
126
- "delete message label": "Delete message",
127
- "accept proposal label": "Accept proposal",
128
- "open comments panel label": "Show Comments",
129
- "comments label": "Comments",
130
- "show all label": "All comments",
131
- "show unresolved label": "Unresolved comments",
132
- "add comment label": "Add comment",
133
- "channel companion label": "Channel",
134
- "call panel label": "Active Call",
135
- "display name label": "Display name",
136
- "display name description": "Set your display name before joining a meeting.",
137
- "display name input placeholder": "Enter your name",
138
- "set display name label": "Continue",
139
- "call tab label": "Call",
140
- "meeting status title": "Calls",
141
- "share meeting link label": "Share meeting",
142
- "show webrtc stats title": "WebRTC Stats",
143
- "show calls history title": "Service History",
144
- "meeting summary label": "Summary",
145
- "summarize label": "Summarize",
146
- "summarizing label": "Creating summary...",
147
- "create summary message": "A summary doesn\u2019t exist for this meeting yet. Create one now?",
148
- "join call": "Join",
149
- "leave call": "Leave",
150
- "lobby participants_zero": "No participants",
151
- "lobby participants_one": "1 participant",
152
- "lobby participants_other": "{{count}} participants",
153
- "icon pin": "Pin video",
154
- "icon unpin": "Unpin video",
155
- "icon wave": "Waving",
156
- "icon muted": "Muted",
157
- "icon speaking": "Speaking",
158
- "mic on": "Unmute",
159
- "mic off": "Mute",
160
- "camera on": "Turn camera on",
161
- "camera off": "Turn camera off",
162
- "camera off label": "Camera off",
163
- "raise hand": "Raise hand",
164
- "lower hand": "Lower hand",
165
- "screenshare on": "Share screen",
166
- "screenshare off": "Stop streaming"
2126
+ [meta2.id]: {
2127
+ "plugin.name": "Chat",
2128
+ "channel-title.label": "Title",
2129
+ "message.placeholder": "Reply\u2026",
2130
+ "activity.message": "Processing\u2026",
2131
+ "anonymous.label": "Anonymous",
2132
+ "delete-message-block.label": "Delete message block",
2133
+ "detached-thread.label": "Referenced content was removed",
2134
+ "delete-thread.label": "Delete thread",
2135
+ "resolve-thread.label": "Resolve thread",
2136
+ "thread-deleted.label": "Thread deleted",
2137
+ "message-deleted.label": "Message deleted",
2138
+ "comments.heading": "Comments",
2139
+ "chat.heading": "Chat",
2140
+ "draft.button": "DRAFT",
2141
+ "no-comments.title": "Comments",
2142
+ "no-comments.message": "Click on the <commentIcon></commentIcon> button in the document toolbar to create a comment thread on the selected text.",
2143
+ "toggle-show-resolved.label": "Show resolved",
2144
+ "unnamed-object-threads.label": "Threads",
2145
+ "mark-as-resolved.label": "Mark as resolved",
2146
+ "mark-as-unresolved.label": "Mark as unresolved",
2147
+ "save-message.label": "Save",
2148
+ "edit-message.label": "Edit",
2149
+ "delete-message.label": "Delete message",
2150
+ "accept-proposal.label": "Accept proposal",
2151
+ "open-comments-panel.label": "Show Comments",
2152
+ "comments.label": "Comments",
2153
+ "show-all.label": "All comments",
2154
+ "show-unresolved.label": "Unresolved comments",
2155
+ "add-comment.label": "Add comment",
2156
+ "channel-companion.label": "Channel",
2157
+ "call-panel.label": "Active Call",
2158
+ "display-name.label": "Display name",
2159
+ "display-name.description": "Set your display name before joining a meeting.",
2160
+ "display-name-input.placeholder": "Enter your name",
2161
+ "set-display-name.label": "Continue",
2162
+ "call-tab.label": "Call",
2163
+ "meeting-status.title": "Calls",
2164
+ "share-meeting-link.label": "Share meeting",
2165
+ "show-webrtc-stats.title": "WebRTC Stats",
2166
+ "show-calls-history.title": "Service History",
2167
+ "meeting-summary.label": "Summary",
2168
+ "summarize.label": "Summarize",
2169
+ "summarizing.label": "Creating summary...",
2170
+ "create-summary.message": "A summary doesn\u2019t exist for this meeting yet. Create one now?",
2171
+ "icon-pin.label": "Pin video",
2172
+ "icon-unpin.label": "Unpin video",
2173
+ "icon-wave.label": "Waving",
2174
+ "icon-muted.label": "Muted",
2175
+ "join-call.button": "Join",
2176
+ "leave-call.button": "Leave",
2177
+ "mic-on.button": "Unmute",
2178
+ "mic-off.button": "Mute",
2179
+ "camera-on.button": "Turn camera on",
2180
+ "camera-off.button": "Turn camera off",
2181
+ "camera-off.label": "Camera off",
2182
+ "raise-hand.button": "Raise hand",
2183
+ "lower-hand.button": "Lower hand",
2184
+ "screenshare-on.button": "Share screen",
2185
+ "screenshare-off.button": "Stop streaming",
2186
+ "channel-toolbar.title": "Channel actions",
2187
+ "start-video-call.menu": "Start video call"
167
2188
  }
168
2189
  }
169
2190
  }
170
2191
  ];
171
2192
 
172
2193
  // src/ThreadPlugin.tsx
173
- var ThreadPlugin = Plugin.define(meta).pipe(
2194
+ var ThreadPlugin = Plugin.define(meta3).pipe(
174
2195
  AppPlugin.addAppGraphModule({
175
2196
  activate: AppGraphBuilder
176
2197
  }),
@@ -180,11 +2201,19 @@ var ThreadPlugin = Plugin.define(meta).pipe(
180
2201
  AppPlugin.addMetadataModule({
181
2202
  metadata: [
182
2203
  {
183
- id: Type2.getTypename(Channel_exports.Channel),
2204
+ id: Type2.getTypename(Channel2.Channel),
184
2205
  metadata: {
185
- icon: "ph--hash--regular",
186
- iconHue: "rose",
187
- createObject: (props) => Effect.sync(() => Channel_exports.make(props))
2206
+ icon: Annotation.IconAnnotation.get(Channel2.Channel).pipe(Option.getOrThrow).icon,
2207
+ iconHue: Annotation.IconAnnotation.get(Channel2.Channel).pipe(Option.getOrThrow).hue ?? "white",
2208
+ createObject: (props, options) => Effect.gen(function* () {
2209
+ const object = Channel2.make(props);
2210
+ return yield* Operation.invoke(SpaceOperation.AddObject, {
2211
+ object,
2212
+ target: options.target,
2213
+ hidden: true,
2214
+ targetNodeId: options.targetNodeId
2215
+ });
2216
+ })
188
2217
  }
189
2218
  },
190
2219
  {
@@ -195,14 +2224,7 @@ var ThreadPlugin = Plugin.define(meta).pipe(
195
2224
  }
196
2225
  },
197
2226
  {
198
- id: Message.Message.typename,
199
- metadata: {
200
- // TODO(wittjosiah): Move out of metadata.
201
- loadReferences: () => []
202
- }
203
- },
204
- {
205
- id: THREAD_ITEM,
2227
+ id: THREAD_ITEM2,
206
2228
  metadata: {
207
2229
  parse: (item, type) => {
208
2230
  switch (type) {
@@ -225,8 +2247,12 @@ var ThreadPlugin = Plugin.define(meta).pipe(
225
2247
  }
226
2248
  ]
227
2249
  }),
228
- AppPlugin.addOperationResolverModule({
229
- activate: OperationResolver
2250
+ AppPlugin.addOperationHandlerModule({
2251
+ activate: OperationHandler
2252
+ }),
2253
+ AppPlugin.addOperationHandlerModule({
2254
+ id: "undo-mappings",
2255
+ activate: UndoMappings
230
2256
  }),
231
2257
  AppPlugin.addReactRootModule({
232
2258
  activate: ReactRoot
@@ -234,9 +2260,8 @@ var ThreadPlugin = Plugin.define(meta).pipe(
234
2260
  AppPlugin.addSchemaModule({
235
2261
  schema: [
236
2262
  AnchoredTo.AnchoredTo,
237
- Channel_exports.Channel,
2263
+ Channel2.Channel,
238
2264
  Message.Message,
239
- Message.MessageV1,
240
2265
  Thread.Thread
241
2266
  ]
242
2267
  }),
@@ -268,22 +2293,10 @@ var ThreadPlugin = Plugin.define(meta).pipe(
268
2293
  activatesOn: AppActivationEvents.SetupSettings,
269
2294
  activate: ThreadState
270
2295
  }),
271
- Plugin.addModule({
272
- id: "migration",
273
- activatesOn: ClientEvents.SetupMigration,
274
- activate: () => Effect.succeed(Capability11.contributes(ClientCapabilities.Migration, [
275
- Message.MessageV1ToV2
276
- ]))
277
- }),
278
2296
  Plugin.addModule({
279
2297
  id: "on-space-created",
280
2298
  activatesOn: SpaceEvents.SpaceCreated,
281
- activate: () => Effect.succeed(Capability11.contributes(SpaceCapabilities.OnCreateSpace, (params) => Operation.invoke(ThreadOperation.OnCreateSpace, params)))
282
- }),
283
- Plugin.addModule({
284
- id: "repair",
285
- activatesOn: ClientEvents.SpacesReady,
286
- activate: Repair
2299
+ activate: () => Effect.succeed(Capability.contributes(SpaceCapabilities.OnCreateSpace, (params) => Operation.invoke(ThreadOperation.OnCreateSpace, params)))
287
2300
  }),
288
2301
  Plugin.addModule({
289
2302
  id: "markdown",