@dxos/plugin-thread 0.8.3 → 0.8.4-main.1c7ec43d41

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 (558) hide show
  1. package/dist/lib/browser/add-message-3FTZANTW.mjs +89 -0
  2. package/dist/lib/browser/add-message-3FTZANTW.mjs.map +7 -0
  3. package/dist/lib/browser/append-channel-message-CO3M6FSA.mjs +40 -0
  4. package/dist/lib/browser/append-channel-message-CO3M6FSA.mjs.map +7 -0
  5. package/dist/lib/browser/blueprints/index.mjs +37 -0
  6. package/dist/lib/browser/blueprints/index.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  8. package/dist/lib/browser/chunk-MR4CWITF.mjs +31 -0
  9. package/dist/lib/browser/chunk-MR4CWITF.mjs.map +7 -0
  10. package/dist/lib/browser/chunk-TPNZ43NB.mjs +258 -0
  11. package/dist/lib/browser/chunk-TPNZ43NB.mjs.map +7 -0
  12. package/dist/lib/browser/create-GMUAPFZM.mjs +55 -0
  13. package/dist/lib/browser/create-GMUAPFZM.mjs.map +7 -0
  14. package/dist/lib/browser/create-channel-ZXKSLHGN.mjs +19 -0
  15. package/dist/lib/browser/create-channel-ZXKSLHGN.mjs.map +7 -0
  16. package/dist/lib/browser/create-proposals-AV5CREPV.mjs +56 -0
  17. package/dist/lib/browser/create-proposals-AV5CREPV.mjs.map +7 -0
  18. package/dist/lib/browser/delete-673YOWCG.mjs +59 -0
  19. package/dist/lib/browser/delete-673YOWCG.mjs.map +7 -0
  20. package/dist/lib/browser/delete-message-RQ72ZY5D.mjs +55 -0
  21. package/dist/lib/browser/delete-message-RQ72ZY5D.mjs.map +7 -0
  22. package/dist/lib/browser/index.mjs +1783 -270
  23. package/dist/lib/browser/index.mjs.map +4 -4
  24. package/dist/lib/browser/meta.json +1 -1
  25. package/dist/lib/browser/on-create-space-SPE3QVFZ.mjs +24 -0
  26. package/dist/lib/browser/on-create-space-SPE3QVFZ.mjs.map +7 -0
  27. package/dist/lib/browser/operations/index.mjs +13 -0
  28. package/dist/lib/browser/operations/index.mjs.map +7 -0
  29. package/dist/lib/browser/restore-VX7FLZOZ.mjs +32 -0
  30. package/dist/lib/browser/restore-VX7FLZOZ.mjs.map +7 -0
  31. package/dist/lib/browser/restore-message-D65NSWUA.mjs +33 -0
  32. package/dist/lib/browser/restore-message-D65NSWUA.mjs.map +7 -0
  33. package/dist/lib/browser/select-DO4AYSCB.mjs +26 -0
  34. package/dist/lib/browser/select-DO4AYSCB.mjs.map +7 -0
  35. package/dist/lib/browser/toggle-resolved-JD3D4WBZ.mjs +36 -0
  36. package/dist/lib/browser/toggle-resolved-JD3D4WBZ.mjs.map +7 -0
  37. package/dist/lib/browser/translations.mjs +90 -0
  38. package/dist/lib/browser/translations.mjs.map +7 -0
  39. package/dist/lib/browser/types/index.mjs +6 -12
  40. package/dist/lib/node-esm/add-message-56J2HLJB.mjs +90 -0
  41. package/dist/lib/node-esm/add-message-56J2HLJB.mjs.map +7 -0
  42. package/dist/lib/node-esm/append-channel-message-F7KGBSWP.mjs +41 -0
  43. package/dist/lib/node-esm/append-channel-message-F7KGBSWP.mjs.map +7 -0
  44. package/dist/lib/node-esm/blueprints/index.mjs +38 -0
  45. package/dist/lib/node-esm/blueprints/index.mjs.map +7 -0
  46. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  47. package/dist/lib/node-esm/chunk-L6UL3NVS.mjs +32 -0
  48. package/dist/lib/node-esm/chunk-L6UL3NVS.mjs.map +7 -0
  49. package/dist/lib/node-esm/chunk-XKUMDYGR.mjs +259 -0
  50. package/dist/lib/node-esm/chunk-XKUMDYGR.mjs.map +7 -0
  51. package/dist/lib/node-esm/create-LEXHIPUT.mjs +56 -0
  52. package/dist/lib/node-esm/create-LEXHIPUT.mjs.map +7 -0
  53. package/dist/lib/node-esm/create-channel-6VHTC2OR.mjs +20 -0
  54. package/dist/lib/node-esm/create-channel-6VHTC2OR.mjs.map +7 -0
  55. package/dist/lib/node-esm/create-proposals-P5O2ICOL.mjs +57 -0
  56. package/dist/lib/node-esm/create-proposals-P5O2ICOL.mjs.map +7 -0
  57. package/dist/lib/node-esm/delete-4KSU4UEJ.mjs +60 -0
  58. package/dist/lib/node-esm/delete-4KSU4UEJ.mjs.map +7 -0
  59. package/dist/lib/node-esm/delete-message-PGNLB6TL.mjs +56 -0
  60. package/dist/lib/node-esm/delete-message-PGNLB6TL.mjs.map +7 -0
  61. package/dist/lib/node-esm/index.mjs +1783 -270
  62. package/dist/lib/node-esm/index.mjs.map +4 -4
  63. package/dist/lib/node-esm/meta.json +1 -1
  64. package/dist/lib/node-esm/on-create-space-TFBSHWQ4.mjs +25 -0
  65. package/dist/lib/node-esm/on-create-space-TFBSHWQ4.mjs.map +7 -0
  66. package/dist/lib/node-esm/operations/index.mjs +14 -0
  67. package/dist/lib/node-esm/operations/index.mjs.map +7 -0
  68. package/dist/lib/node-esm/restore-E27OAIFJ.mjs +33 -0
  69. package/dist/lib/node-esm/restore-E27OAIFJ.mjs.map +7 -0
  70. package/dist/lib/node-esm/restore-message-J3CH6NGI.mjs +34 -0
  71. package/dist/lib/node-esm/restore-message-J3CH6NGI.mjs.map +7 -0
  72. package/dist/lib/node-esm/select-NDHRM75K.mjs +27 -0
  73. package/dist/lib/node-esm/select-NDHRM75K.mjs.map +7 -0
  74. package/dist/lib/node-esm/toggle-resolved-VS6NKXL3.mjs +37 -0
  75. package/dist/lib/node-esm/toggle-resolved-VS6NKXL3.mjs.map +7 -0
  76. package/dist/lib/node-esm/translations.mjs +91 -0
  77. package/dist/lib/node-esm/translations.mjs.map +7 -0
  78. package/dist/lib/node-esm/types/index.mjs +6 -12
  79. package/dist/types/src/ThreadPlugin.d.ts +3 -1
  80. package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
  81. package/dist/types/src/ThreadPlugin.node.d.ts +4 -0
  82. package/dist/types/src/ThreadPlugin.node.d.ts.map +1 -0
  83. package/dist/types/src/ThreadPlugin.test.d.ts +2 -0
  84. package/dist/types/src/ThreadPlugin.test.d.ts.map +1 -0
  85. package/dist/types/src/blueprints/index.d.ts +2 -0
  86. package/dist/types/src/blueprints/index.d.ts.map +1 -0
  87. package/dist/types/src/blueprints/thread-blueprint.d.ts +4 -0
  88. package/dist/types/src/blueprints/thread-blueprint.d.ts.map +1 -0
  89. package/dist/types/src/calls/call-manager.d.ts +40 -30
  90. package/dist/types/src/calls/call-manager.d.ts.map +1 -1
  91. package/dist/types/src/calls/call-swarm-synchronizer.d.ts +2 -2
  92. package/dist/types/src/calls/call-swarm-synchronizer.d.ts.map +1 -1
  93. package/dist/types/src/calls/media-manager.d.ts +2 -2
  94. package/dist/types/src/calls/media-manager.d.ts.map +1 -1
  95. package/dist/types/src/calls/speaking-monitor.d.ts +0 -3
  96. package/dist/types/src/calls/speaking-monitor.d.ts.map +1 -1
  97. package/dist/types/src/calls/types.d.ts +1 -1
  98. package/dist/types/src/calls/types.d.ts.map +1 -1
  99. package/dist/types/src/calls/util/audio.d.ts.map +1 -1
  100. package/dist/types/src/calls/util/calls-service.d.ts +11 -6
  101. package/dist/types/src/calls/util/calls-service.d.ts.map +1 -1
  102. package/dist/types/src/calls/util/history-cache.d.ts.map +1 -1
  103. package/dist/types/src/calls/util/media.d.ts.map +1 -1
  104. package/dist/types/src/calls/util/stub-media-streams.d.ts.map +1 -1
  105. package/dist/types/src/calls/util/task-scheduling.d.ts +2 -2
  106. package/dist/types/src/calls/util/task-scheduling.d.ts.map +1 -1
  107. package/dist/types/src/calls-service.stories.d.ts +23 -0
  108. package/dist/types/src/calls-service.stories.d.ts.map +1 -0
  109. package/dist/types/src/capabilities/app-graph-builder.d.ts +4 -2
  110. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  111. package/dist/types/src/capabilities/blueprint-definition.d.ts +6 -0
  112. package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -0
  113. package/dist/types/src/capabilities/call-manager.d.ts +3 -2
  114. package/dist/types/src/capabilities/call-manager.d.ts.map +1 -1
  115. package/dist/types/src/capabilities/create-object.d.ts +11 -0
  116. package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
  117. package/dist/types/src/capabilities/index.d.ts +19 -13
  118. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  119. package/dist/types/src/capabilities/markdown.d.ts +3 -2
  120. package/dist/types/src/capabilities/markdown.d.ts.map +1 -1
  121. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  122. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  123. package/dist/types/src/capabilities/react-root.d.ts +4 -2
  124. package/dist/types/src/capabilities/react-root.d.ts.map +1 -1
  125. package/dist/types/src/capabilities/react-surface.d.ts +3 -2
  126. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  127. package/dist/types/src/capabilities/settings.d.ts +5 -2
  128. package/dist/types/src/capabilities/settings.d.ts.map +1 -1
  129. package/dist/types/src/capabilities/state.d.ts +5 -5
  130. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  131. package/dist/types/src/capabilities/undo-mappings.d.ts +5 -0
  132. package/dist/types/src/capabilities/undo-mappings.d.ts.map +1 -0
  133. package/dist/types/src/components/Call/Call.d.ts +32 -4
  134. package/dist/types/src/components/Call/Call.d.ts.map +1 -1
  135. package/dist/types/src/components/Call/Toolbar.d.ts +6 -6
  136. package/dist/types/src/components/Call/Toolbar.d.ts.map +1 -1
  137. package/dist/types/src/components/Chat/Chat.d.ts +51 -0
  138. package/dist/types/src/components/Chat/Chat.d.ts.map +1 -0
  139. package/dist/types/src/components/Chat/index.d.ts +2 -0
  140. package/dist/types/src/components/Chat/index.d.ts.map +1 -0
  141. package/dist/types/src/components/CommentsPanel/CommentsPanel.d.ts +13 -0
  142. package/dist/types/src/components/CommentsPanel/CommentsPanel.d.ts.map +1 -0
  143. package/dist/types/src/components/CommentsPanel/CommentsPanel.stories.d.ts +160 -0
  144. package/dist/types/src/components/CommentsPanel/CommentsPanel.stories.d.ts.map +1 -0
  145. package/dist/types/src/components/CommentsPanel/CommentsThread.d.ts +14 -0
  146. package/dist/types/src/components/CommentsPanel/CommentsThread.d.ts.map +1 -0
  147. package/dist/types/src/components/CommentsPanel/index.d.ts +3 -0
  148. package/dist/types/src/components/CommentsPanel/index.d.ts.map +1 -0
  149. package/dist/types/src/components/Lobby/Lobby.d.ts +24 -3
  150. package/dist/types/src/components/Lobby/Lobby.d.ts.map +1 -1
  151. package/dist/types/src/components/Media/VideoObject.d.ts +3 -3
  152. package/dist/types/src/components/Media/VideoObject.d.ts.map +1 -1
  153. package/dist/types/src/components/Media/VideoObject.stories.d.ts +18 -4
  154. package/dist/types/src/components/Media/VideoObject.stories.d.ts.map +1 -1
  155. package/dist/types/src/components/MessagePanel/MessagePanel.d.ts +15 -0
  156. package/dist/types/src/components/MessagePanel/MessagePanel.d.ts.map +1 -0
  157. package/dist/types/src/components/MessagePanel/index.d.ts +2 -0
  158. package/dist/types/src/components/MessagePanel/index.d.ts.map +1 -0
  159. package/dist/types/src/components/Participant/Participant.d.ts.map +1 -1
  160. package/dist/types/src/components/Participant/ParticipantGrid.d.ts.map +1 -1
  161. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.d.ts.map +1 -1
  162. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts +160 -5
  163. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts.map +1 -1
  164. package/dist/types/src/components/ResponsiveGrid/ResponsiveGridItem.d.ts.map +1 -1
  165. package/dist/types/src/components/ResponsiveGrid/{ResponsiveContainer.d.ts → ResponsivePanel.d.ts} +4 -4
  166. package/dist/types/src/components/ResponsiveGrid/ResponsivePanel.d.ts.map +1 -0
  167. package/dist/types/src/components/ResponsiveGrid/ResponsivePanel.stories.d.ts +164 -0
  168. package/dist/types/src/components/ResponsiveGrid/ResponsivePanel.stories.d.ts.map +1 -0
  169. package/dist/types/src/components/ResponsiveGrid/index.d.ts +1 -1
  170. package/dist/types/src/components/ResponsiveGrid/index.d.ts.map +1 -1
  171. package/dist/types/src/components/ThreadSettings/ThreadSettings.d.ts +6 -0
  172. package/dist/types/src/components/ThreadSettings/ThreadSettings.d.ts.map +1 -0
  173. package/dist/types/src/components/ThreadSettings/ThreadSettings.stories.d.ts +161 -0
  174. package/dist/types/src/components/ThreadSettings/ThreadSettings.stories.d.ts.map +1 -0
  175. package/dist/types/src/components/ThreadSettings/index.d.ts +2 -0
  176. package/dist/types/src/components/ThreadSettings/index.d.ts.map +1 -0
  177. package/dist/types/src/components/index.d.ts +5 -9
  178. package/dist/types/src/components/index.d.ts.map +1 -1
  179. package/dist/types/src/containers/CallDebugPanel/CallDebugPanel.d.ts +15 -0
  180. package/dist/types/src/containers/CallDebugPanel/CallDebugPanel.d.ts.map +1 -0
  181. package/dist/types/src/containers/CallDebugPanel/index.d.ts +2 -0
  182. package/dist/types/src/containers/CallDebugPanel/index.d.ts.map +1 -0
  183. package/dist/types/src/{components → containers/CallSidebar}/CallSidebar.d.ts +0 -1
  184. package/dist/types/src/containers/CallSidebar/CallSidebar.d.ts.map +1 -0
  185. package/dist/types/src/containers/CallSidebar/index.d.ts +2 -0
  186. package/dist/types/src/containers/CallSidebar/index.d.ts.map +1 -0
  187. package/dist/types/src/containers/ChannelChat/ChannelChat.d.ts +20 -0
  188. package/dist/types/src/containers/ChannelChat/ChannelChat.d.ts.map +1 -0
  189. package/dist/types/src/containers/ChannelChat/index.d.ts +4 -0
  190. package/dist/types/src/containers/ChannelChat/index.d.ts.map +1 -0
  191. package/dist/types/src/containers/ChannelContainer/ChannelContainer.d.ts +12 -0
  192. package/dist/types/src/containers/ChannelContainer/ChannelContainer.d.ts.map +1 -0
  193. package/dist/types/src/containers/ChannelContainer/ChannelContainer.stories.d.ts +162 -0
  194. package/dist/types/src/containers/ChannelContainer/ChannelContainer.stories.d.ts.map +1 -0
  195. package/dist/types/src/containers/ChannelContainer/index.d.ts +2 -0
  196. package/dist/types/src/containers/ChannelContainer/index.d.ts.map +1 -0
  197. package/dist/types/src/containers/ThreadCompanion/ThreadCompanion.d.ts +8 -0
  198. package/dist/types/src/containers/ThreadCompanion/ThreadCompanion.d.ts.map +1 -0
  199. package/dist/types/src/containers/ThreadCompanion/index.d.ts +2 -0
  200. package/dist/types/src/containers/ThreadCompanion/index.d.ts.map +1 -0
  201. package/dist/types/src/containers/ThreadContainer/ThreadContainer.d.ts +20 -0
  202. package/dist/types/src/containers/ThreadContainer/ThreadContainer.d.ts.map +1 -0
  203. package/dist/types/src/containers/ThreadContainer/ThreadContainer.stories.d.ts +162 -0
  204. package/dist/types/src/containers/ThreadContainer/ThreadContainer.stories.d.ts.map +1 -0
  205. package/dist/types/src/containers/ThreadContainer/index.d.ts +4 -0
  206. package/dist/types/src/containers/ThreadContainer/index.d.ts.map +1 -0
  207. package/dist/types/src/containers/index.d.ts +8 -0
  208. package/dist/types/src/containers/index.d.ts.map +1 -0
  209. package/dist/types/src/{components/command-extension.d.ts → extensions/command.d.ts} +1 -1
  210. package/dist/types/src/extensions/command.d.ts.map +1 -0
  211. package/dist/types/src/extensions/index.d.ts +1 -0
  212. package/dist/types/src/extensions/index.d.ts.map +1 -1
  213. package/dist/types/src/extensions/threads.d.ts +9 -4
  214. package/dist/types/src/extensions/threads.d.ts.map +1 -1
  215. package/dist/types/src/hooks/analytics.d.ts +2 -3
  216. package/dist/types/src/hooks/analytics.d.ts.map +1 -1
  217. package/dist/types/src/hooks/index.d.ts +3 -0
  218. package/dist/types/src/hooks/index.d.ts.map +1 -1
  219. package/dist/types/src/hooks/useBlackCanvasStreamTrack.d.ts +2 -0
  220. package/dist/types/src/hooks/useBlackCanvasStreamTrack.d.ts.map +1 -0
  221. package/dist/types/src/hooks/useInaudibleAudioStreamTrack.d.ts +2 -0
  222. package/dist/types/src/hooks/useInaudibleAudioStreamTrack.d.ts.map +1 -0
  223. package/dist/types/src/hooks/useStatus.d.ts.map +1 -1
  224. package/dist/types/src/hooks/useVideoStreamTrack.d.ts +3 -0
  225. package/dist/types/src/hooks/useVideoStreamTrack.d.ts.map +1 -0
  226. package/dist/types/src/index.d.ts +4 -3
  227. package/dist/types/src/index.d.ts.map +1 -1
  228. package/dist/types/src/meta.d.ts +3 -4
  229. package/dist/types/src/meta.d.ts.map +1 -1
  230. package/dist/types/src/operations/add-message.d.ts +5 -0
  231. package/dist/types/src/operations/add-message.d.ts.map +1 -0
  232. package/dist/types/src/operations/append-channel-message.d.ts +5 -0
  233. package/dist/types/src/operations/append-channel-message.d.ts.map +1 -0
  234. package/dist/types/src/operations/create-channel.d.ts +5 -0
  235. package/dist/types/src/operations/create-channel.d.ts.map +1 -0
  236. package/dist/types/src/operations/create-proposals.d.ts +5 -0
  237. package/dist/types/src/operations/create-proposals.d.ts.map +1 -0
  238. package/dist/types/src/operations/create.d.ts +5 -0
  239. package/dist/types/src/operations/create.d.ts.map +1 -0
  240. package/dist/types/src/operations/definitions.d.ts +1995 -0
  241. package/dist/types/src/operations/definitions.d.ts.map +1 -0
  242. package/dist/types/src/operations/delete-message.d.ts +5 -0
  243. package/dist/types/src/operations/delete-message.d.ts.map +1 -0
  244. package/dist/types/src/operations/delete.d.ts +5 -0
  245. package/dist/types/src/operations/delete.d.ts.map +1 -0
  246. package/dist/types/src/operations/index.d.ts +4 -0
  247. package/dist/types/src/operations/index.d.ts.map +1 -0
  248. package/dist/types/src/operations/on-create-space.d.ts +5 -0
  249. package/dist/types/src/operations/on-create-space.d.ts.map +1 -0
  250. package/dist/types/src/operations/restore-message.d.ts +5 -0
  251. package/dist/types/src/operations/restore-message.d.ts.map +1 -0
  252. package/dist/types/src/operations/restore.d.ts +5 -0
  253. package/dist/types/src/operations/restore.d.ts.map +1 -0
  254. package/dist/types/src/operations/select.d.ts +5 -0
  255. package/dist/types/src/operations/select.d.ts.map +1 -0
  256. package/dist/types/src/operations/toggle-resolved.d.ts +5 -0
  257. package/dist/types/src/operations/toggle-resolved.d.ts.map +1 -0
  258. package/dist/types/src/testing/data.d.ts +5 -0
  259. package/dist/types/src/testing/data.d.ts.map +1 -0
  260. package/dist/types/src/testing/index.d.ts +1 -1
  261. package/dist/types/src/testing/index.d.ts.map +1 -1
  262. package/dist/types/src/translations.d.ts +144 -194
  263. package/dist/types/src/translations.d.ts.map +1 -1
  264. package/dist/types/src/types/Settings.d.ts +5 -0
  265. package/dist/types/src/types/Settings.d.ts.map +1 -0
  266. package/dist/types/src/types/capabilities.d.ts +29 -0
  267. package/dist/types/src/types/capabilities.d.ts.map +1 -0
  268. package/dist/types/src/types/index.d.ts +1 -1
  269. package/dist/types/src/types/index.d.ts.map +1 -1
  270. package/dist/types/src/types/types.d.ts +4 -326
  271. package/dist/types/src/types/types.d.ts.map +1 -1
  272. package/dist/types/src/util.d.ts +21 -3
  273. package/dist/types/src/util.d.ts.map +1 -1
  274. package/dist/types/tsconfig.tsbuildinfo +1 -1
  275. package/package.json +119 -75
  276. package/src/ThreadPlugin.node.ts +39 -0
  277. package/src/ThreadPlugin.test.ts +37 -0
  278. package/src/ThreadPlugin.tsx +66 -149
  279. package/src/blueprints/index.ts +5 -0
  280. package/src/blueprints/thread-blueprint.ts +36 -0
  281. package/src/calls/call-manager.ts +78 -50
  282. package/src/calls/call-swarm-synchronizer.ts +3 -3
  283. package/src/calls/media-manager.ts +77 -41
  284. package/src/calls/types.ts +8 -4
  285. package/src/calls/util/calls-service.ts +74 -19
  286. package/src/calls/util/stub-media-streams.ts +65 -9
  287. package/src/calls/util/task-scheduling.ts +4 -4
  288. package/src/calls-service.stories.tsx +230 -0
  289. package/src/capabilities/app-graph-builder.ts +177 -162
  290. package/src/capabilities/blueprint-definition.ts +19 -0
  291. package/src/capabilities/call-manager.ts +19 -11
  292. package/src/capabilities/create-object.ts +29 -0
  293. package/src/capabilities/index.ts +17 -11
  294. package/src/capabilities/markdown.ts +55 -37
  295. package/src/capabilities/operation-handler.ts +16 -0
  296. package/src/capabilities/react-root.tsx +12 -9
  297. package/src/capabilities/react-surface.tsx +83 -74
  298. package/src/capabilities/settings.ts +28 -12
  299. package/src/capabilities/state.ts +14 -17
  300. package/src/capabilities/undo-mappings.ts +46 -0
  301. package/src/components/Call/Call.tsx +17 -12
  302. package/src/components/Call/Toolbar.tsx +63 -46
  303. package/src/components/Chat/Chat.tsx +258 -0
  304. package/src/components/Chat/index.ts +5 -0
  305. package/src/components/CommentsPanel/CommentsPanel.stories.tsx +95 -0
  306. package/src/components/CommentsPanel/CommentsPanel.tsx +71 -0
  307. package/src/components/CommentsPanel/CommentsThread.tsx +172 -0
  308. package/src/components/CommentsPanel/index.ts +6 -0
  309. package/src/components/Lobby/Lobby.tsx +21 -17
  310. package/src/components/Media/AudioStream.tsx +2 -2
  311. package/src/components/Media/VideoObject.stories.tsx +37 -30
  312. package/src/components/Media/VideoObject.tsx +1 -1
  313. package/src/components/MessagePanel/MessagePanel.tsx +225 -0
  314. package/src/components/MessagePanel/index.ts +5 -0
  315. package/src/components/Participant/Participant.tsx +35 -15
  316. package/src/components/Participant/ParticipantGrid.tsx +1 -1
  317. package/src/components/ResponsiveGrid/ResponsiveGrid.stories.tsx +51 -49
  318. package/src/components/ResponsiveGrid/ResponsiveGrid.tsx +6 -6
  319. package/src/components/ResponsiveGrid/ResponsiveGridItem.tsx +15 -12
  320. package/src/components/ResponsiveGrid/{ResponsiveContainer.stories.tsx → ResponsivePanel.stories.tsx} +12 -12
  321. package/src/components/ResponsiveGrid/{ResponsiveContainer.tsx → ResponsivePanel.tsx} +5 -5
  322. package/src/components/ResponsiveGrid/index.ts +1 -1
  323. package/src/components/ThreadSettings/ThreadSettings.stories.tsx +32 -0
  324. package/src/components/ThreadSettings/ThreadSettings.tsx +20 -0
  325. package/src/components/ThreadSettings/index.ts +5 -0
  326. package/src/components/index.ts +6 -12
  327. package/src/containers/CallDebugPanel/CallDebugPanel.tsx +173 -0
  328. package/src/containers/CallDebugPanel/index.ts +5 -0
  329. package/src/containers/CallSidebar/CallSidebar.tsx +18 -0
  330. package/src/containers/CallSidebar/index.ts +5 -0
  331. package/src/containers/ChannelChat/ChannelChat.tsx +75 -0
  332. package/src/containers/ChannelChat/index.ts +8 -0
  333. package/src/containers/ChannelContainer/ChannelContainer.stories.tsx +105 -0
  334. package/src/containers/ChannelContainer/ChannelContainer.tsx +223 -0
  335. package/src/containers/ChannelContainer/index.ts +5 -0
  336. package/src/containers/ThreadCompanion/ThreadCompanion.tsx +215 -0
  337. package/src/containers/ThreadCompanion/index.ts +5 -0
  338. package/src/containers/ThreadContainer/ThreadContainer.stories.tsx +86 -0
  339. package/src/containers/ThreadContainer/ThreadContainer.tsx +75 -0
  340. package/src/containers/ThreadContainer/index.ts +8 -0
  341. package/src/containers/index.ts +12 -0
  342. package/src/{components/command-extension.ts → extensions/command.ts} +7 -4
  343. package/src/extensions/index.ts +1 -0
  344. package/src/extensions/threads.ts +89 -44
  345. package/src/hooks/analytics.ts +22 -21
  346. package/src/hooks/index.ts +4 -0
  347. package/src/hooks/useBlackCanvasStreamTrack.tsx +27 -0
  348. package/src/hooks/useDebugMode.ts +1 -1
  349. package/src/hooks/useInaudibleAudioStreamTrack.tsx +27 -0
  350. package/src/hooks/useVideoStreamTrack.tsx +36 -0
  351. package/src/index.ts +11 -4
  352. package/src/meta.ts +11 -7
  353. package/src/operations/add-message.ts +81 -0
  354. package/src/operations/append-channel-message.ts +36 -0
  355. package/src/operations/create-channel.ts +20 -0
  356. package/src/operations/create-proposals.ts +49 -0
  357. package/src/operations/create.ts +48 -0
  358. package/src/operations/definitions.ts +177 -0
  359. package/src/operations/delete-message.ts +53 -0
  360. package/src/operations/delete.ts +63 -0
  361. package/src/operations/index.ts +22 -0
  362. package/src/operations/on-create-space.ts +27 -0
  363. package/src/operations/restore-message.ts +38 -0
  364. package/src/operations/restore.ts +38 -0
  365. package/src/operations/select.ts +24 -0
  366. package/src/operations/toggle-resolved.ts +41 -0
  367. package/src/testing/data.ts +49 -0
  368. package/src/testing/index.ts +1 -1
  369. package/src/translations.ts +77 -73
  370. package/src/types/Settings.ts +10 -0
  371. package/src/types/capabilities.ts +42 -0
  372. package/src/types/index.ts +1 -1
  373. package/src/types/types.ts +5 -91
  374. package/src/typings/peermetrics-webrtc-stats.d.ts +17 -1
  375. package/src/typings.d.ts +8 -0
  376. package/src/util.ts +38 -6
  377. package/dist/lib/browser/ChannelContainer-PKFBVENP.mjs +0 -15
  378. package/dist/lib/browser/ChatContainer-RSOKYAMK.mjs +0 -14
  379. package/dist/lib/browser/app-graph-builder-OY7R7EJP.mjs +0 -171
  380. package/dist/lib/browser/app-graph-builder-OY7R7EJP.mjs.map +0 -7
  381. package/dist/lib/browser/call-manager-APQAZWHT.mjs +0 -23
  382. package/dist/lib/browser/call-manager-APQAZWHT.mjs.map +0 -7
  383. package/dist/lib/browser/chunk-4H4A264L.mjs +0 -1708
  384. package/dist/lib/browser/chunk-4H4A264L.mjs.map +0 -7
  385. package/dist/lib/browser/chunk-5P5BH5GE.mjs +0 -88
  386. package/dist/lib/browser/chunk-5P5BH5GE.mjs.map +0 -7
  387. package/dist/lib/browser/chunk-6NBVNXTM.mjs +0 -21
  388. package/dist/lib/browser/chunk-6NBVNXTM.mjs.map +0 -7
  389. package/dist/lib/browser/chunk-AEXWNS6Z.mjs +0 -128
  390. package/dist/lib/browser/chunk-AEXWNS6Z.mjs.map +0 -7
  391. package/dist/lib/browser/chunk-IIUTBDVB.mjs +0 -17
  392. package/dist/lib/browser/chunk-IIUTBDVB.mjs.map +0 -7
  393. package/dist/lib/browser/chunk-JKQUJOTX.mjs +0 -31
  394. package/dist/lib/browser/chunk-JKQUJOTX.mjs.map +0 -7
  395. package/dist/lib/browser/chunk-PG5CTFKK.mjs +0 -550
  396. package/dist/lib/browser/chunk-PG5CTFKK.mjs.map +0 -7
  397. package/dist/lib/browser/chunk-R5MDLUPC.mjs +0 -18
  398. package/dist/lib/browser/chunk-R5MDLUPC.mjs.map +0 -7
  399. package/dist/lib/browser/chunk-TAFSCSUR.mjs +0 -351
  400. package/dist/lib/browser/chunk-TAFSCSUR.mjs.map +0 -7
  401. package/dist/lib/browser/chunk-XZKBN3NS.mjs +0 -983
  402. package/dist/lib/browser/chunk-XZKBN3NS.mjs.map +0 -7
  403. package/dist/lib/browser/intent-resolver-FK2MDVDT.mjs +0 -353
  404. package/dist/lib/browser/intent-resolver-FK2MDVDT.mjs.map +0 -7
  405. package/dist/lib/browser/markdown-TE5SWWNJ.mjs +0 -169
  406. package/dist/lib/browser/markdown-TE5SWWNJ.mjs.map +0 -7
  407. package/dist/lib/browser/react-root-NK3A4VG7.mjs +0 -27
  408. package/dist/lib/browser/react-root-NK3A4VG7.mjs.map +0 -7
  409. package/dist/lib/browser/react-surface-VXUJKSOG.mjs +0 -108
  410. package/dist/lib/browser/react-surface-VXUJKSOG.mjs.map +0 -7
  411. package/dist/lib/browser/settings-RB2RSLXV.mjs +0 -22
  412. package/dist/lib/browser/settings-RB2RSLXV.mjs.map +0 -7
  413. package/dist/lib/browser/state-RKL5MSDP.mjs +0 -34
  414. package/dist/lib/browser/state-RKL5MSDP.mjs.map +0 -7
  415. package/dist/lib/node/ChannelContainer-YS5YT2ML.cjs +0 -36
  416. package/dist/lib/node/ChannelContainer-YS5YT2ML.cjs.map +0 -7
  417. package/dist/lib/node/ChatContainer-GCOM3M56.cjs +0 -35
  418. package/dist/lib/node/ChatContainer-GCOM3M56.cjs.map +0 -7
  419. package/dist/lib/node/app-graph-builder-PBHJNDQY.cjs +0 -179
  420. package/dist/lib/node/app-graph-builder-PBHJNDQY.cjs.map +0 -7
  421. package/dist/lib/node/call-manager-HV2XJW5O.cjs +0 -37
  422. package/dist/lib/node/call-manager-HV2XJW5O.cjs.map +0 -7
  423. package/dist/lib/node/chunk-44I33JDT.cjs +0 -1731
  424. package/dist/lib/node/chunk-44I33JDT.cjs.map +0 -7
  425. package/dist/lib/node/chunk-4YSNVPWU.cjs +0 -37
  426. package/dist/lib/node/chunk-4YSNVPWU.cjs.map +0 -7
  427. package/dist/lib/node/chunk-E3WBZTTI.cjs +0 -371
  428. package/dist/lib/node/chunk-E3WBZTTI.cjs.map +0 -7
  429. package/dist/lib/node/chunk-ERG7G6FF.cjs +0 -59
  430. package/dist/lib/node/chunk-ERG7G6FF.cjs.map +0 -7
  431. package/dist/lib/node/chunk-FUXJAVFZ.cjs +0 -108
  432. package/dist/lib/node/chunk-FUXJAVFZ.cjs.map +0 -7
  433. package/dist/lib/node/chunk-HLMCEE5K.cjs +0 -41
  434. package/dist/lib/node/chunk-HLMCEE5K.cjs.map +0 -7
  435. package/dist/lib/node/chunk-IP533AMV.cjs +0 -554
  436. package/dist/lib/node/chunk-IP533AMV.cjs.map +0 -7
  437. package/dist/lib/node/chunk-LR5NENBE.cjs +0 -54
  438. package/dist/lib/node/chunk-LR5NENBE.cjs.map +0 -7
  439. package/dist/lib/node/chunk-UM36TPCT.cjs +0 -984
  440. package/dist/lib/node/chunk-UM36TPCT.cjs.map +0 -7
  441. package/dist/lib/node/chunk-ZGDN3XBR.cjs +0 -149
  442. package/dist/lib/node/chunk-ZGDN3XBR.cjs.map +0 -7
  443. package/dist/lib/node/index.cjs +0 -310
  444. package/dist/lib/node/index.cjs.map +0 -7
  445. package/dist/lib/node/intent-resolver-SYSJ5SJG.cjs +0 -363
  446. package/dist/lib/node/intent-resolver-SYSJ5SJG.cjs.map +0 -7
  447. package/dist/lib/node/markdown-GQIPJS2F.cjs +0 -178
  448. package/dist/lib/node/markdown-GQIPJS2F.cjs.map +0 -7
  449. package/dist/lib/node/meta.json +0 -1
  450. package/dist/lib/node/react-root-6HHDMULJ.cjs +0 -51
  451. package/dist/lib/node/react-root-6HHDMULJ.cjs.map +0 -7
  452. package/dist/lib/node/react-surface-NBH42NN2.cjs +0 -122
  453. package/dist/lib/node/react-surface-NBH42NN2.cjs.map +0 -7
  454. package/dist/lib/node/settings-4LQSFEDK.cjs +0 -36
  455. package/dist/lib/node/settings-4LQSFEDK.cjs.map +0 -7
  456. package/dist/lib/node/state-IY5XX3H2.cjs +0 -50
  457. package/dist/lib/node/state-IY5XX3H2.cjs.map +0 -7
  458. package/dist/lib/node/types/index.cjs +0 -38
  459. package/dist/lib/node/types/index.cjs.map +0 -7
  460. package/dist/lib/node-esm/ChannelContainer-O4QJII2P.mjs +0 -16
  461. package/dist/lib/node-esm/ChannelContainer-O4QJII2P.mjs.map +0 -7
  462. package/dist/lib/node-esm/ChatContainer-F6CSADV7.mjs +0 -15
  463. package/dist/lib/node-esm/ChatContainer-F6CSADV7.mjs.map +0 -7
  464. package/dist/lib/node-esm/app-graph-builder-BAHBHYWI.mjs +0 -172
  465. package/dist/lib/node-esm/app-graph-builder-BAHBHYWI.mjs.map +0 -7
  466. package/dist/lib/node-esm/call-manager-UUYXLF4T.mjs +0 -24
  467. package/dist/lib/node-esm/call-manager-UUYXLF4T.mjs.map +0 -7
  468. package/dist/lib/node-esm/chunk-2RNIPFDA.mjs +0 -984
  469. package/dist/lib/node-esm/chunk-2RNIPFDA.mjs.map +0 -7
  470. package/dist/lib/node-esm/chunk-ESQC6SYE.mjs +0 -19
  471. package/dist/lib/node-esm/chunk-ESQC6SYE.mjs.map +0 -7
  472. package/dist/lib/node-esm/chunk-K4KAUOKT.mjs +0 -19
  473. package/dist/lib/node-esm/chunk-K4KAUOKT.mjs.map +0 -7
  474. package/dist/lib/node-esm/chunk-O3V45YJP.mjs +0 -90
  475. package/dist/lib/node-esm/chunk-O3V45YJP.mjs.map +0 -7
  476. package/dist/lib/node-esm/chunk-O63QJPQX.mjs +0 -23
  477. package/dist/lib/node-esm/chunk-O63QJPQX.mjs.map +0 -7
  478. package/dist/lib/node-esm/chunk-P6RLFCNT.mjs +0 -352
  479. package/dist/lib/node-esm/chunk-P6RLFCNT.mjs.map +0 -7
  480. package/dist/lib/node-esm/chunk-PGRP3O4O.mjs +0 -33
  481. package/dist/lib/node-esm/chunk-PGRP3O4O.mjs.map +0 -7
  482. package/dist/lib/node-esm/chunk-UJMPYKT3.mjs +0 -129
  483. package/dist/lib/node-esm/chunk-UJMPYKT3.mjs.map +0 -7
  484. package/dist/lib/node-esm/chunk-UZWVVFT3.mjs +0 -551
  485. package/dist/lib/node-esm/chunk-UZWVVFT3.mjs.map +0 -7
  486. package/dist/lib/node-esm/chunk-WXNPD542.mjs +0 -1710
  487. package/dist/lib/node-esm/chunk-WXNPD542.mjs.map +0 -7
  488. package/dist/lib/node-esm/intent-resolver-BU73VYW3.mjs +0 -354
  489. package/dist/lib/node-esm/intent-resolver-BU73VYW3.mjs.map +0 -7
  490. package/dist/lib/node-esm/markdown-HJUWNBLS.mjs +0 -170
  491. package/dist/lib/node-esm/markdown-HJUWNBLS.mjs.map +0 -7
  492. package/dist/lib/node-esm/react-root-RUXOAQNW.mjs +0 -28
  493. package/dist/lib/node-esm/react-root-RUXOAQNW.mjs.map +0 -7
  494. package/dist/lib/node-esm/react-surface-ELXFYKP6.mjs +0 -109
  495. package/dist/lib/node-esm/react-surface-ELXFYKP6.mjs.map +0 -7
  496. package/dist/lib/node-esm/settings-EA7DFSM6.mjs +0 -23
  497. package/dist/lib/node-esm/settings-EA7DFSM6.mjs.map +0 -7
  498. package/dist/lib/node-esm/state-6AUTNROZ.mjs +0 -35
  499. package/dist/lib/node-esm/state-6AUTNROZ.mjs.map +0 -7
  500. package/dist/types/src/capabilities/capabilities.d.ts +0 -27
  501. package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
  502. package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
  503. package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
  504. package/dist/types/src/components/CallDebugPanel.d.ts +0 -8
  505. package/dist/types/src/components/CallDebugPanel.d.ts.map +0 -1
  506. package/dist/types/src/components/CallSidebar.d.ts.map +0 -1
  507. package/dist/types/src/components/ChannelContainer.d.ts +0 -14
  508. package/dist/types/src/components/ChannelContainer.d.ts.map +0 -1
  509. package/dist/types/src/components/ChannelContainer.stories.d.ts +0 -10
  510. package/dist/types/src/components/ChannelContainer.stories.d.ts.map +0 -1
  511. package/dist/types/src/components/Chat.stories.d.ts +0 -6
  512. package/dist/types/src/components/Chat.stories.d.ts.map +0 -1
  513. package/dist/types/src/components/ChatContainer.d.ts +0 -17
  514. package/dist/types/src/components/ChatContainer.d.ts.map +0 -1
  515. package/dist/types/src/components/CommentContainer.d.ts +0 -13
  516. package/dist/types/src/components/CommentContainer.d.ts.map +0 -1
  517. package/dist/types/src/components/Comments.stories.d.ts +0 -6
  518. package/dist/types/src/components/Comments.stories.d.ts.map +0 -1
  519. package/dist/types/src/components/CommentsContainer.d.ts +0 -13
  520. package/dist/types/src/components/CommentsContainer.d.ts.map +0 -1
  521. package/dist/types/src/components/MessageContainer.d.ts +0 -11
  522. package/dist/types/src/components/MessageContainer.d.ts.map +0 -1
  523. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.d.ts.map +0 -1
  524. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts +0 -10
  525. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts.map +0 -1
  526. package/dist/types/src/components/ThreadComplementary.d.ts +0 -5
  527. package/dist/types/src/components/ThreadComplementary.d.ts.map +0 -1
  528. package/dist/types/src/components/ThreadSettings.d.ts +0 -6
  529. package/dist/types/src/components/ThreadSettings.d.ts.map +0 -1
  530. package/dist/types/src/components/command-extension.d.ts.map +0 -1
  531. package/dist/types/src/components/testing.d.ts +0 -4
  532. package/dist/types/src/components/testing.d.ts.map +0 -1
  533. package/dist/types/src/peers.stories.d.ts +0 -11
  534. package/dist/types/src/peers.stories.d.ts.map +0 -1
  535. package/dist/types/src/testing/stories.d.ts +0 -2
  536. package/dist/types/src/testing/stories.d.ts.map +0 -1
  537. package/dist/types/src/types/schema.d.ts +0 -133
  538. package/dist/types/src/types/schema.d.ts.map +0 -1
  539. package/src/capabilities/capabilities.ts +0 -33
  540. package/src/capabilities/intent-resolver.ts +0 -296
  541. package/src/components/CallDebugPanel.tsx +0 -115
  542. package/src/components/CallSidebar.tsx +0 -17
  543. package/src/components/ChannelContainer.stories.tsx +0 -58
  544. package/src/components/ChannelContainer.tsx +0 -199
  545. package/src/components/Chat.stories.tsx +0 -88
  546. package/src/components/ChatContainer.tsx +0 -140
  547. package/src/components/CommentContainer.tsx +0 -198
  548. package/src/components/Comments.stories.tsx +0 -85
  549. package/src/components/CommentsContainer.tsx +0 -66
  550. package/src/components/MessageContainer.tsx +0 -167
  551. package/src/components/ThreadComplementary.tsx +0 -151
  552. package/src/components/ThreadSettings.tsx +0 -17
  553. package/src/components/testing.ts +0 -29
  554. package/src/peers.stories.tsx +0 -189
  555. package/src/testing/stories.ts +0 -50
  556. package/src/types/schema.ts +0 -33
  557. /package/dist/lib/browser/{ChannelContainer-PKFBVENP.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
  558. /package/dist/lib/{browser/ChatContainer-RSOKYAMK.mjs.map → node-esm/chunk-HSLMI22Q.mjs.map} +0 -0
@@ -2,17 +2,16 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { computed } from '@preact/signals-core';
5
+ import { Atom, type Registry } from '@effect-atom/atom-react';
6
6
 
7
7
  import { Event, synchronized } from '@dxos/async';
8
8
  import { type Client } from '@dxos/client';
9
9
  import { Resource } from '@dxos/context';
10
10
  import { invariant } from '@dxos/invariant';
11
- import { live } from '@dxos/live-object';
12
11
  import { type Tracks } from '@dxos/protocols/proto/dxos/edge/calls';
13
12
  import { isNonNullable } from '@dxos/util';
14
13
 
15
- import { CallSwarmSynchronizer, type CallState } from './call-swarm-synchronizer';
14
+ import { type CallState, CallSwarmSynchronizer } from './call-swarm-synchronizer';
16
15
  import { MediaManager, type MediaState } from './media-manager';
17
16
  import { type ActivityState, CALLS_URL, type EncodedTrackName, TrackNameCodec, type UserState } from './types';
18
17
 
@@ -31,80 +30,103 @@ export class CallManager extends Resource {
31
30
  public readonly left = new Event<string>();
32
31
 
33
32
  /**
34
- * Live object state. Is changed on internal events.
33
+ * Atom-based state. Updated via `_updateState()`.
35
34
  * CAUTION: Do not change directly.
36
35
  */
37
- private readonly _state = live<GlobalState>({
36
+ private readonly _stateAtom = Atom.make<GlobalState>({
38
37
  call: {},
39
38
  media: { pulledAudioTracks: {}, pulledVideoStreams: {} },
40
39
  });
41
40
 
42
- // TODO(wittjosiah): This shouldn't be necessary, live-object's signals should be granular.
43
- private readonly _raisedHandSignal = computed(() => this._state.call.raisedHand ?? false);
44
- private readonly _speakingSignal = computed(() => this._state.call.speaking ?? false);
45
- private readonly _joinedSignal = computed(() => this._state.call.joined ?? false);
41
+ // Derived atoms for reactive subscriptions.
42
+ private readonly _roomIdAtom = Atom.make((get) => get(this._stateAtom).call.roomId);
43
+ private readonly _raisedHandAtom = Atom.make((get) => get(this._stateAtom).call.raisedHand ?? false);
44
+ private readonly _speakingAtom = Atom.make((get) => get(this._stateAtom).call.speaking ?? false);
45
+ private readonly _joinedAtom = Atom.make((get) => get(this._stateAtom).call.joined ?? false);
46
+ private readonly _selfAtom = Atom.make((get) => get(this._stateAtom).call.self ?? {});
47
+ private readonly _tracksAtom = Atom.make((get) => get(this._stateAtom).call.tracks ?? {});
48
+ private readonly _usersAtom = Atom.make((get) => get(this._stateAtom).call.users ?? []);
49
+ private readonly _mediaAtom = Atom.make((get) => get(this._stateAtom).media);
50
+ private readonly _audioTracksToPlayAtom = Atom.make((get) => {
51
+ const state = get(this._stateAtom);
52
+ return (state.call.users ?? [])
53
+ .map((user: UserState) => (user.tracks?.audioEnabled ? user.tracks?.audio : undefined))
54
+ .filter(isNonNullable)
55
+ .map((track: string) => state.media.pulledAudioTracks[track as EncodedTrackName]?.track)
56
+ .filter(isNonNullable);
57
+ });
58
+ private readonly _videoStreamAtomFamily = Atom.family<EncodedTrackName, Atom.Atom<MediaStream | undefined>>((name) =>
59
+ Atom.make((get) => get(this._stateAtom).media.pulledVideoStreams[name]?.stream),
60
+ );
61
+ private readonly _activityAtomFamily = Atom.family<string, Atom.Atom<ActivityState | undefined>>((key) =>
62
+ Atom.make((get) => get(this._stateAtom).call.activities?.[key]),
63
+ );
46
64
 
47
65
  private readonly _swarmSynchronizer: CallSwarmSynchronizer;
48
66
  private readonly _mediaManager: MediaManager;
49
67
 
50
- /** @reactive */
51
- get roomId(): string | undefined {
52
- return this._state.call.roomId;
68
+ //
69
+ // Derived atoms for reactive UI subscriptions.
70
+ //
71
+
72
+ /** Derived atom for roomId. */
73
+ get roomIdAtom(): Atom.Atom<string | undefined> {
74
+ return this._roomIdAtom;
53
75
  }
54
76
 
55
- /** @reactive */
56
- get raisedHand(): boolean {
57
- return this._raisedHandSignal.value;
77
+ /** Derived atom for raisedHand. */
78
+ get raisedHandAtom(): Atom.Atom<boolean> {
79
+ return this._raisedHandAtom;
58
80
  }
59
81
 
60
- /** @reactive */
61
- get speaking(): boolean {
62
- return this._speakingSignal.value;
82
+ /** Derived atom for speaking. */
83
+ get speakingAtom(): Atom.Atom<boolean> {
84
+ return this._speakingAtom;
63
85
  }
64
86
 
65
- /** @reactive */
66
- get joined(): boolean {
67
- return this._joinedSignal.value;
87
+ /** Derived atom for joined. */
88
+ get joinedAtom(): Atom.Atom<boolean> {
89
+ return this._joinedAtom;
68
90
  }
69
91
 
70
- /** @reactive */
71
- get self(): UserState {
72
- return this._state.call.self ?? {};
92
+ /** Derived atom for self. */
93
+ get selfAtom(): Atom.Atom<UserState> {
94
+ return this._selfAtom;
73
95
  }
74
96
 
75
- /** @reactive */
76
- get tracks(): Tracks {
77
- return this._state.call.tracks ?? {};
97
+ /** Derived atom for tracks. */
98
+ get tracksAtom(): Atom.Atom<Tracks> {
99
+ return this._tracksAtom;
78
100
  }
79
101
 
80
- /** @reactive */
81
- get users(): UserState[] {
82
- return this._state.call.users ?? [];
102
+ /** Derived atom for users. */
103
+ get usersAtom(): Atom.Atom<UserState[]> {
104
+ return this._usersAtom;
83
105
  }
84
106
 
85
- /** @reactive */
86
- get media() {
87
- return this._state.media;
107
+ /** Derived atom for media. */
108
+ get mediaAtom(): Atom.Atom<MediaState> {
109
+ return this._mediaAtom;
88
110
  }
89
111
 
90
- /** @reactive */
91
- get pulledAudioTracks() {
92
- return Object.values(this._state.media.pulledAudioTracks).map((track) => track.track);
112
+ /** Derived atom for audioTracksToPlay. */
113
+ get audioTracksToPlayAtom(): Atom.Atom<MediaStreamTrack[]> {
114
+ return this._audioTracksToPlayAtom;
93
115
  }
94
116
 
95
- /** @reactive */
96
- get state() {
97
- return this._state;
117
+ /** Returns the full state atom for reactive subscriptions. */
118
+ get stateAtom(): Atom.Atom<GlobalState> {
119
+ return this._stateAtom;
98
120
  }
99
121
 
100
- /** @reactive */
101
- getVideoStream(name?: EncodedTrackName): MediaStream | undefined {
102
- return name ? this._state.media.pulledVideoStreams[name]?.stream : undefined;
122
+ /** Returns a derived atom for a video stream by name. */
123
+ videoStreamAtom(name: EncodedTrackName): Atom.Atom<MediaStream | undefined> {
124
+ return this._videoStreamAtomFamily(name);
103
125
  }
104
126
 
105
- /** @reactive */
106
- getActivity(key: string): ActivityState | undefined {
107
- return this._state.call.activities?.[key];
127
+ /** Returns a derived atom for an activity by key. */
128
+ activityAtom(key: string): Atom.Atom<ActivityState | undefined> {
129
+ return this._activityAtomFamily(key);
108
130
  }
109
131
 
110
132
  setRoomId(roomId: string): void {
@@ -148,7 +170,10 @@ export class CallManager extends Resource {
148
170
  }
149
171
 
150
172
  // TODO(burdon): Can this be mocked?
151
- constructor(private readonly _client: Client) {
173
+ constructor(
174
+ private readonly _client: Client,
175
+ private readonly _registry: Registry.Registry,
176
+ ) {
152
177
  super();
153
178
  this._client.config.getOrThrow('runtime.services.edge.url');
154
179
  const networkService = this._client.services.services.NetworkService;
@@ -201,12 +226,13 @@ export class CallManager extends Resource {
201
226
  this._swarmSynchronizer.setJoined(false);
202
227
  await this._swarmSynchronizer.leave();
203
228
  await this._mediaManager.leave();
204
- this.roomId && this.left.emit(this.roomId);
229
+ const roomId = this._registry.get(this._roomIdAtom);
230
+ roomId && this.left.emit(roomId);
205
231
  }
206
232
 
207
233
  private _onCallStateUpdated(state: CallState): void {
208
234
  const tracksToPull = state.users
209
- ?.filter((user) => user.joined && user.id !== state.self?.id)
235
+ ?.filter((user) => user.joined && user.id !== state.self!.id)
210
236
  ?.flatMap((user) => [user.tracks?.video, user.tracks?.audio, user.tracks?.screenshare])
211
237
  .filter(isNonNullable);
212
238
  this._mediaManager._schedulePullTracks(tracksToPull as EncodedTrackName[]);
@@ -236,7 +262,9 @@ export class CallManager extends Resource {
236
262
  * Only this method is allowed to change state.
237
263
  */
238
264
  private _updateState(): void {
239
- this._state.call = this._swarmSynchronizer._getState();
240
- this._state.media = this._mediaManager._getState();
265
+ this._registry.set(this._stateAtom, {
266
+ call: this._swarmSynchronizer._getState(),
267
+ media: this._mediaManager._getState(),
268
+ });
241
269
  }
242
270
  }
@@ -17,7 +17,7 @@ import { type Device, type NetworkService } from '@dxos/protocols/proto/dxos/cli
17
17
  import { ConnectionState, type SwarmResponse } from '@dxos/protocols/proto/dxos/edge/messenger';
18
18
  import { isNonNullable } from '@dxos/util';
19
19
 
20
- import { codec, type ActivityState, type UserState } from './types';
20
+ import { type ActivityState, type UserState, codec } from './types';
21
21
 
22
22
  export type CallState = {
23
23
  /**
@@ -50,7 +50,7 @@ export type CallState = {
50
50
  tracks?: UserState['tracks'];
51
51
  };
52
52
 
53
- export type CallSwarmSynchronizerParams = { networkService: NetworkService };
53
+ export type CallSwarmSynchronizerProps = { networkService: NetworkService };
54
54
 
55
55
  /**
56
56
  * Period for peer to reconnect to the call swarm gracefully if connection was lost abruptly.
@@ -76,7 +76,7 @@ export class CallSwarmSynchronizer extends Resource {
76
76
 
77
77
  private _sendStateTask?: DeferredTask = undefined;
78
78
 
79
- constructor({ networkService }: CallSwarmSynchronizerParams) {
79
+ constructor({ networkService }: CallSwarmSynchronizerProps) {
80
80
  super();
81
81
  this._networkService = networkService;
82
82
  }
@@ -3,11 +3,12 @@
3
3
  //
4
4
 
5
5
  import { DeferredTask, Event, sleep, synchronized } from '@dxos/async';
6
- import { cancelWithContext, type Context, Resource } from '@dxos/context';
6
+ import { type Context, Resource, cancelWithContext } from '@dxos/context';
7
+ import { invariant } from '@dxos/invariant';
7
8
  import { log } from '@dxos/log';
8
9
 
9
10
  import { SpeakingMonitor } from './speaking-monitor';
10
- import { TrackNameCodec, type EncodedTrackName, type TrackObject } from './types';
11
+ import { type EncodedTrackName, TrackNameCodec, type TrackObject } from './types';
11
12
  import {
12
13
  type CallsServiceConfig,
13
14
  CallsServicePeer,
@@ -48,17 +49,23 @@ const VIDEO_WIDTH = 1280;
48
49
  const VIDEO_HEIGHT = 720;
49
50
  const MAX_WEB_CAM_FRAMERATE = 24;
50
51
  const MAX_WEB_CAM_BITRATE = 120_0000;
51
- const RETRY_INTERVAL = 500;
52
+ const RETRY_INTERVAL = 100;
52
53
 
53
- export type MediaManagerParams = {
54
+ export type MediaManagerProps = {
54
55
  serviceConfig: CallsServiceConfig;
55
56
  };
56
57
 
58
+ const USE_INAUDIBLE_AUDIO = true;
59
+
57
60
  export class MediaManager extends Resource {
58
61
  public readonly stateUpdated = new Event<MediaState>();
59
- private readonly _state: MediaState = { pulledVideoStreams: {}, pulledAudioTracks: {} };
60
- private _speakingMonitor?: SpeakingMonitor = undefined;
61
62
 
63
+ private readonly _state: MediaState = {
64
+ pulledVideoStreams: {},
65
+ pulledAudioTracks: {},
66
+ };
67
+
68
+ private _speakingMonitor?: SpeakingMonitor = undefined;
62
69
  private _trackToReconcile: EncodedTrackName[] = [];
63
70
  private _blackCanvasStreamTrack?: MediaStreamTrack = undefined;
64
71
  private _inaudibleAudioStreamTrack?: MediaStreamTrack = undefined;
@@ -82,12 +89,15 @@ export class MediaManager extends Resource {
82
89
  width: VIDEO_WIDTH,
83
90
  height: VIDEO_HEIGHT,
84
91
  });
92
+
85
93
  this._state.videoTrack = this._blackCanvasStreamTrack;
86
94
  this._state.videoStream = new MediaStream();
87
95
  this._state.videoStream.addTrack(this._state.videoTrack);
88
96
 
89
- this._inaudibleAudioStreamTrack = await createInaudibleAudioStreamTrack({ ctx: this._ctx });
90
- this._state.audioTrack = this._inaudibleAudioStreamTrack;
97
+ if (USE_INAUDIBLE_AUDIO) {
98
+ this._inaudibleAudioStreamTrack = await createInaudibleAudioStreamTrack({ ctx: this._ctx });
99
+ this._state.audioTrack = this._inaudibleAudioStreamTrack;
100
+ }
91
101
 
92
102
  this._pushTracksTask = new DeferredTask(this._ctx, async () => {
93
103
  await this._pushTracks();
@@ -132,6 +142,7 @@ export class MediaManager extends Resource {
132
142
  this._state.videoStream!.removeTrack(this._state.videoTrack!);
133
143
  this._state.videoTrack = await getUserMediaTrack('videoinput', { width: VIDEO_WIDTH, height: VIDEO_HEIGHT });
134
144
  this._state.videoStream!.addTrack(this._state.videoTrack);
145
+
135
146
  this._state.videoEnabled = true;
136
147
  this.stateUpdated.emit(this._state);
137
148
  this._pushTracksTask!.schedule();
@@ -170,11 +181,14 @@ export class MediaManager extends Resource {
170
181
  async turnAudioOff(): Promise<void> {
171
182
  void this._speakingMonitor?.close();
172
183
  this._speakingMonitor = undefined;
173
- if (this._state.audioTrack !== this._inaudibleAudioStreamTrack) {
184
+ this._state.audioEnabled = false;
185
+ if (USE_INAUDIBLE_AUDIO && this._state.audioTrack !== this._inaudibleAudioStreamTrack) {
174
186
  this._state.audioTrack?.stop();
175
187
  this._state.audioTrack = this._inaudibleAudioStreamTrack;
188
+ } else {
189
+ this._state.audioTrack?.stop();
190
+ this._state.audioTrack = undefined;
176
191
  }
177
- this._state.audioEnabled = false;
178
192
  this.stateUpdated.emit(this._state);
179
193
  this._pushTracksTask!.schedule();
180
194
  }
@@ -218,7 +232,6 @@ export class MediaManager extends Resource {
218
232
  // Wait for cloudflare to process the track.
219
233
  await cancelWithContext(this._ctx, sleep(800));
220
234
  const trackNames = this._trackToReconcile;
221
-
222
235
  const tracksToPull = trackNames.filter(
223
236
  (name) => !this._state.pulledAudioTracks[name] && !this._state.pulledVideoStreams[name],
224
237
  );
@@ -241,7 +254,7 @@ export class MediaManager extends Resource {
241
254
  });
242
255
 
243
256
  // Pull new tracks.
244
- await Promise.all(tracksToPull.map((name) => this._pullTrack(name)));
257
+ const pullResults = await Promise.all(tracksToPull.map((name) => this._pullTrack(name)));
245
258
 
246
259
  // Close old tracks.
247
260
  await Promise.all([...audioTracksToClose, ...videoStreamsToClose].map(([_, { ctx }]) => ctx.dispose()));
@@ -250,7 +263,14 @@ export class MediaManager extends Resource {
250
263
  currentAudioTracks: Object.keys(this._state.pulledAudioTracks),
251
264
  currentVideoStreams: Object.keys(this._state.pulledVideoStreams),
252
265
  });
266
+
253
267
  this.stateUpdated.emit(this._state);
268
+ if (pullResults.some(({ shouldRetry }) => shouldRetry)) {
269
+ await cancelWithContext(this._ctx, sleep(RETRY_INTERVAL));
270
+ log.info('retrying pull tracks', { tracksToPull });
271
+ invariant(this._pullTracksTask);
272
+ this._pullTracksTask.schedule();
273
+ }
254
274
  }
255
275
 
256
276
  private async _pushTracks(): Promise<void> {
@@ -259,38 +279,46 @@ export class MediaManager extends Resource {
259
279
  }
260
280
 
261
281
  let updated = false;
262
- const [pushedVideoTrack, pushedAudioTrack, pushedScreenshareTrack] = await Promise.all([
263
- this._pushTrack(this._state.videoTrack, this._state.pushedVideoTrack, [
282
+ const [pushVideoResult, pushAudioResult, pushScreenshareResult] = await Promise.all([
283
+ this._maybePushTrack(this._state.videoTrack, this._state.pushedVideoTrack, [
264
284
  { maxFramerate: MAX_WEB_CAM_FRAMERATE, maxBitrate: MAX_WEB_CAM_BITRATE },
265
285
  ]),
266
- this._pushTrack(this._state.audioTrack, this._state.pushedAudioTrack, [{ networkPriority: 'high' }]),
267
- this._pushTrack(this._state.screenshareTrack, this._state.pushedScreenshareTrack),
286
+ this._maybePushTrack(this._state.audioTrack, this._state.pushedAudioTrack, [{ networkPriority: 'high' }]),
287
+ this._maybePushTrack(this._state.screenshareTrack, this._state.pushedScreenshareTrack),
268
288
  ]);
269
289
 
270
- if (pushedVideoTrack !== this._state.pushedVideoTrack) {
271
- this._state.pushedVideoTrack = pushedVideoTrack;
290
+ if (pushVideoResult.track !== this._state.pushedVideoTrack) {
291
+ this._state.pushedVideoTrack = pushVideoResult.track;
272
292
  updated = true;
273
293
  }
274
- if (pushedAudioTrack !== this._state.pushedAudioTrack) {
275
- this._state.pushedAudioTrack = pushedAudioTrack;
294
+ if (pushAudioResult.track !== this._state.pushedAudioTrack) {
295
+ this._state.pushedAudioTrack = pushAudioResult.track;
276
296
  updated = true;
277
297
  }
278
- if (pushedScreenshareTrack !== this._state.pushedScreenshareTrack) {
279
- this._state.pushedScreenshareTrack = pushedScreenshareTrack;
298
+ if (pushScreenshareResult.track !== this._state.pushedScreenshareTrack) {
299
+ this._state.pushedScreenshareTrack = pushScreenshareResult.track;
280
300
  updated = true;
281
301
  }
282
- if (!updated) {
283
- return;
302
+
303
+ const shouldRetry = pushVideoResult.shouldRetry || pushAudioResult.shouldRetry || pushScreenshareResult.shouldRetry;
304
+ if (updated) {
305
+ this.stateUpdated.emit(this._state);
284
306
  }
285
307
 
286
- this.stateUpdated.emit(this._state);
308
+ if (shouldRetry) {
309
+ await cancelWithContext(this._ctx, sleep(RETRY_INTERVAL));
310
+ log.info('retrying push tracks', { pushVideoResult, pushAudioResult, pushScreenshareResult });
311
+ invariant(this._pushTracksTask);
312
+ this._pushTracksTask.schedule();
313
+ }
287
314
  }
288
315
 
289
- private async _pullTrack(name: EncodedTrackName): Promise<void> {
316
+ private async _pullTrack(name: EncodedTrackName): Promise<{ shouldRetry: boolean }> {
290
317
  const ctx = this._ctx.derive();
291
318
  try {
292
319
  const trackData = TrackNameCodec.decode(name);
293
- const track = await this._state.peer!.pullTrack({ trackData, ctx });
320
+ // We need to set mid here to `undefined`, because mid is peer specific.
321
+ const track = await this._state.peer!.pullTrack({ trackData: { ...trackData, mid: undefined }, ctx });
294
322
  if (track?.readyState === 'ended') {
295
323
  throw new Error('Pulled track ended immediately');
296
324
  }
@@ -299,7 +327,7 @@ export class MediaManager extends Resource {
299
327
  case 'audio': {
300
328
  this._state.pulledAudioTracks[name] = { track, ctx };
301
329
  ctx.onDispose(() => delete this._state.pulledAudioTracks[name]);
302
- break;
330
+ return { shouldRetry: false };
303
331
  }
304
332
  case 'video': {
305
333
  const mediaStream = new MediaStream();
@@ -310,33 +338,41 @@ export class MediaManager extends Resource {
310
338
  track.stop();
311
339
  delete this._state.pulledVideoStreams[name];
312
340
  });
313
- break;
341
+ return { shouldRetry: false };
314
342
  }
315
343
  default:
316
344
  throw new Error(`Invalid track kind: ${track?.kind}`);
317
345
  }
318
346
  } catch (err) {
319
- log.verbose('failed to pull track', { err, name });
347
+ log.info('failed to pull track', { err, name });
320
348
  void ctx.dispose();
321
- await cancelWithContext(this._ctx, sleep(RETRY_INTERVAL));
322
- log.verbose('retrying pull track', { name });
323
- this._pullTracksTask!.schedule();
349
+ return { shouldRetry: true };
324
350
  }
325
351
  }
326
352
 
327
- private async _pushTrack(
353
+ private async _maybePushTrack(
328
354
  track?: MediaStreamTrack,
329
355
  previousTrack?: TrackObject,
330
356
  encodings?: RTCRtpEncodingParameters[],
331
- ): Promise<TrackObject | undefined> {
357
+ ): Promise<{ track?: TrackObject; shouldRetry?: boolean }> {
332
358
  if (!track && !previousTrack) {
333
- return;
359
+ return { track: undefined };
334
360
  }
335
361
 
336
- return this._state.peer!.pushTrack({
337
- track: track ?? null,
338
- previousTrack,
339
- encodings,
340
- });
362
+ const ctx = this._ctx.derive();
363
+ try {
364
+ return {
365
+ track: await this._state.peer!.pushTrack({
366
+ ctx,
367
+ track: track ?? null,
368
+ previousTrack,
369
+ encodings,
370
+ }),
371
+ };
372
+ } catch (err) {
373
+ log.info('failed to push track', { err, track, previousTrack, encodings });
374
+ void ctx.dispose();
375
+ return { shouldRetry: true };
376
+ }
341
377
  }
342
378
  }
@@ -2,11 +2,12 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { invariant } from '@dxos/invariant';
5
6
  import { buf } from '@dxos/protocols/buf';
6
7
  import {
7
8
  type ActivitySchema,
8
- UserStateSchema,
9
9
  type UserState as UserStateProto,
10
+ UserStateSchema,
10
11
  } from '@dxos/protocols/buf/dxos/edge/calls_pb';
11
12
 
12
13
  /**
@@ -61,10 +62,13 @@ export type EncodedTrackName = string & { __brand: 'EncodedTrackName' };
61
62
 
62
63
  export const TrackNameCodec = {
63
64
  encode: (trackData: TrackObject): EncodedTrackName => {
64
- return (trackData.sessionId + '/' + trackData.trackName) as EncodedTrackName;
65
+ invariant(trackData.sessionId);
66
+ invariant(trackData.trackName);
67
+ invariant(trackData.mid);
68
+ return (trackData.sessionId + '/' + trackData.trackName + '/' + trackData.mid) as EncodedTrackName;
65
69
  },
66
70
  decode: (name: EncodedTrackName): TrackObject => {
67
- const [sessionId, trackName] = name.split('/');
68
- return { sessionId, trackName, location: 'remote' };
71
+ const [sessionId, trackName, mid] = name.split('/');
72
+ return { sessionId, trackName, location: 'remote', mid };
69
73
  },
70
74
  };