@dxos/plugin-thread 0.8.4-main.67995b8 → 0.8.4-main.c4373fc

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 (283) hide show
  1. package/dist/lib/browser/ChannelContainer-BGDGZHV4.mjs +16 -0
  2. package/dist/lib/browser/ChatContainer-75KJZ4XR.mjs +15 -0
  3. package/dist/lib/browser/{app-graph-builder-N7BE5TYW.mjs → app-graph-builder-ODKIAXR7.mjs} +19 -19
  4. package/dist/lib/browser/app-graph-builder-ODKIAXR7.mjs.map +7 -0
  5. package/dist/lib/browser/{call-manager-NIPDYUVD.mjs → call-manager-BCKLI4QD.mjs} +7 -7
  6. package/dist/lib/browser/call-manager-BCKLI4QD.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-2MUYQOQE.mjs +23 -0
  8. package/dist/lib/browser/{chunk-FR7KJPNY.mjs.map → chunk-2MUYQOQE.mjs.map} +3 -3
  9. package/dist/lib/browser/chunk-B7YQ7QR2.mjs +376 -0
  10. package/dist/lib/browser/chunk-B7YQ7QR2.mjs.map +7 -0
  11. package/dist/lib/browser/{chunk-KWPRNHTK.mjs → chunk-CMCVHULC.mjs} +235 -233
  12. package/dist/lib/browser/chunk-CMCVHULC.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-GERVMFQW.mjs → chunk-CP7E2HRE.mjs} +2 -2
  14. package/dist/lib/browser/chunk-CP7E2HRE.mjs.map +7 -0
  15. package/dist/lib/browser/{chunk-ERWASUQK.mjs → chunk-HDEQRBOC.mjs} +38 -6
  16. package/dist/lib/{node-esm/chunk-25ABSYP2.mjs.map → browser/chunk-HDEQRBOC.mjs.map} +4 -4
  17. package/dist/lib/browser/chunk-L326LSNS.mjs +18 -0
  18. package/dist/lib/browser/chunk-L326LSNS.mjs.map +7 -0
  19. package/dist/lib/browser/{chunk-EV4JWI7L.mjs → chunk-T4KJ5JR4.mjs} +5 -7
  20. package/dist/lib/browser/chunk-T4KJ5JR4.mjs.map +7 -0
  21. package/dist/lib/browser/chunk-VJMKS4CZ.mjs +619 -0
  22. package/dist/lib/browser/chunk-VJMKS4CZ.mjs.map +7 -0
  23. package/dist/lib/browser/{chunk-GCLD5ESP.mjs → chunk-VTYX3SIM.mjs} +26 -16
  24. package/dist/lib/browser/chunk-VTYX3SIM.mjs.map +7 -0
  25. package/dist/lib/browser/{chunk-6NSMBO3B.mjs → chunk-XYUJXHYV.mjs} +55 -5
  26. package/dist/lib/browser/chunk-XYUJXHYV.mjs.map +7 -0
  27. package/dist/lib/browser/{chunk-ZE7KWN36.mjs → chunk-ZCEU5K23.mjs} +461 -240
  28. package/dist/lib/browser/chunk-ZCEU5K23.mjs.map +7 -0
  29. package/dist/lib/browser/index.mjs +23 -14
  30. package/dist/lib/browser/index.mjs.map +3 -3
  31. package/dist/lib/browser/{intent-resolver-JFGLZ6VI.mjs → intent-resolver-VOQD3TQ2.mjs} +75 -17
  32. package/dist/lib/browser/intent-resolver-VOQD3TQ2.mjs.map +7 -0
  33. package/dist/lib/browser/{markdown-M3FMR7OD.mjs → markdown-R6MGRIA6.mjs} +7 -7
  34. package/dist/lib/browser/markdown-R6MGRIA6.mjs.map +7 -0
  35. package/dist/lib/browser/meta.json +1 -1
  36. package/dist/lib/browser/react-root-UMSBTN6H.mjs +28 -0
  37. package/dist/lib/browser/react-root-UMSBTN6H.mjs.map +7 -0
  38. package/dist/lib/browser/{react-surface-XWS6GIZY.mjs → react-surface-SXMQEWKE.mjs} +22 -22
  39. package/dist/lib/browser/react-surface-SXMQEWKE.mjs.map +7 -0
  40. package/dist/lib/browser/{settings-E32MTL7A.mjs → settings-TCNF54PN.mjs} +5 -5
  41. package/dist/lib/browser/{settings-E32MTL7A.mjs.map → settings-TCNF54PN.mjs.map} +1 -1
  42. package/dist/lib/browser/{state-H6CYONWE.mjs → state-ZQ4IPOJT.mjs} +5 -5
  43. package/dist/lib/browser/state-ZQ4IPOJT.mjs.map +7 -0
  44. package/dist/lib/browser/toolkit-JF4B4QIO.mjs +84 -0
  45. package/dist/lib/browser/toolkit-JF4B4QIO.mjs.map +7 -0
  46. package/dist/lib/browser/types/index.mjs +2 -2
  47. package/dist/lib/node-esm/ChannelContainer-OXC6BTU7.mjs +17 -0
  48. package/dist/lib/node-esm/{ChatContainer-IQUWU426.mjs → ChatContainer-SH6LTFQL.mjs} +6 -6
  49. package/dist/lib/node-esm/{app-graph-builder-VCW76Z6V.mjs → app-graph-builder-DMPT3MY6.mjs} +19 -19
  50. package/dist/lib/node-esm/app-graph-builder-DMPT3MY6.mjs.map +7 -0
  51. package/dist/lib/node-esm/{call-manager-D6O5ZJJ4.mjs → call-manager-Q7RY2YP4.mjs} +7 -7
  52. package/dist/lib/node-esm/call-manager-Q7RY2YP4.mjs.map +7 -0
  53. package/dist/lib/node-esm/{chunk-C3XFMUAY.mjs → chunk-2KZ4ODHU.mjs} +235 -233
  54. package/dist/lib/node-esm/chunk-2KZ4ODHU.mjs.map +7 -0
  55. package/dist/lib/node-esm/{chunk-25ABSYP2.mjs → chunk-2MMJF7DW.mjs} +38 -6
  56. package/dist/lib/node-esm/chunk-2MMJF7DW.mjs.map +7 -0
  57. package/dist/lib/node-esm/{chunk-OU5BYIDO.mjs → chunk-2V3WSLUZ.mjs} +55 -5
  58. package/dist/lib/node-esm/chunk-2V3WSLUZ.mjs.map +7 -0
  59. package/dist/lib/node-esm/{chunk-57XR3LEF.mjs → chunk-ABUFOZVX.mjs} +2 -2
  60. package/dist/lib/node-esm/chunk-ABUFOZVX.mjs.map +7 -0
  61. package/dist/lib/node-esm/{chunk-TDFHTCZZ.mjs → chunk-BAMZXJS4.mjs} +26 -16
  62. package/dist/lib/node-esm/chunk-BAMZXJS4.mjs.map +7 -0
  63. package/dist/lib/node-esm/chunk-BTGKI5IK.mjs +377 -0
  64. package/dist/lib/node-esm/chunk-BTGKI5IK.mjs.map +7 -0
  65. package/dist/lib/node-esm/chunk-GZ4WL2IS.mjs +25 -0
  66. package/dist/lib/node-esm/{chunk-2CXOK2TD.mjs.map → chunk-GZ4WL2IS.mjs.map} +3 -3
  67. package/dist/lib/node-esm/chunk-LCHTNRK7.mjs +19 -0
  68. package/dist/lib/node-esm/chunk-LCHTNRK7.mjs.map +7 -0
  69. package/dist/lib/node-esm/chunk-NHSIAEDW.mjs +620 -0
  70. package/dist/lib/node-esm/chunk-NHSIAEDW.mjs.map +7 -0
  71. package/dist/lib/node-esm/{chunk-GRLRWTRU.mjs → chunk-OBVAURUU.mjs} +5 -7
  72. package/dist/lib/node-esm/chunk-OBVAURUU.mjs.map +7 -0
  73. package/dist/lib/node-esm/{chunk-IHDNQLLR.mjs → chunk-TIPIOH2J.mjs} +461 -240
  74. package/dist/lib/node-esm/chunk-TIPIOH2J.mjs.map +7 -0
  75. package/dist/lib/node-esm/index.mjs +23 -14
  76. package/dist/lib/node-esm/index.mjs.map +3 -3
  77. package/dist/lib/node-esm/{intent-resolver-OXGNQ44Y.mjs → intent-resolver-AKVH66PH.mjs} +75 -17
  78. package/dist/lib/node-esm/intent-resolver-AKVH66PH.mjs.map +7 -0
  79. package/dist/lib/node-esm/{markdown-INKTE4MH.mjs → markdown-MYGTDXT6.mjs} +7 -7
  80. package/dist/lib/node-esm/markdown-MYGTDXT6.mjs.map +7 -0
  81. package/dist/lib/node-esm/meta.json +1 -1
  82. package/dist/lib/node-esm/react-root-W6AVTL5M.mjs +29 -0
  83. package/dist/lib/node-esm/react-root-W6AVTL5M.mjs.map +7 -0
  84. package/dist/lib/node-esm/{react-surface-MJ33KPYE.mjs → react-surface-NLSZJGMO.mjs} +22 -22
  85. package/dist/lib/node-esm/react-surface-NLSZJGMO.mjs.map +7 -0
  86. package/dist/lib/node-esm/{settings-SJ24YG7M.mjs → settings-ZQHGVFBY.mjs} +5 -5
  87. package/dist/lib/node-esm/{settings-SJ24YG7M.mjs.map → settings-ZQHGVFBY.mjs.map} +1 -1
  88. package/dist/lib/node-esm/{state-D7WNDT3N.mjs → state-FSLLJ5TZ.mjs} +5 -5
  89. package/dist/lib/node-esm/state-FSLLJ5TZ.mjs.map +7 -0
  90. package/dist/lib/node-esm/toolkit-DHPKJITO.mjs +85 -0
  91. package/dist/lib/node-esm/toolkit-DHPKJITO.mjs.map +7 -0
  92. package/dist/lib/node-esm/types/index.mjs +2 -2
  93. package/dist/types/src/ThreadPlugin.d.ts +1 -1
  94. package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
  95. package/dist/types/src/calls/call-manager.d.ts.map +1 -1
  96. package/dist/types/src/calls/call-swarm-synchronizer.d.ts.map +1 -1
  97. package/dist/types/src/calls/media-manager.d.ts +1 -1
  98. package/dist/types/src/calls/media-manager.d.ts.map +1 -1
  99. package/dist/types/src/calls/types.d.ts +1 -1
  100. package/dist/types/src/calls/types.d.ts.map +1 -1
  101. package/dist/types/src/calls/util/calls-service.d.ts +4 -2
  102. package/dist/types/src/calls/util/calls-service.d.ts.map +1 -1
  103. package/dist/types/src/calls/util/stub-media-streams.d.ts.map +1 -1
  104. package/dist/types/src/calls-service.stories.d.ts +10 -9
  105. package/dist/types/src/calls-service.stories.d.ts.map +1 -1
  106. package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
  107. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  108. package/dist/types/src/capabilities/call-manager.d.ts +1 -1
  109. package/dist/types/src/capabilities/call-manager.d.ts.map +1 -1
  110. package/dist/types/src/capabilities/capabilities.d.ts +2 -2
  111. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  112. package/dist/types/src/capabilities/index.d.ts +11 -10
  113. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  114. package/dist/types/src/capabilities/intent-resolver.d.ts +1 -1
  115. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  116. package/dist/types/src/capabilities/markdown.d.ts +1 -1
  117. package/dist/types/src/capabilities/markdown.d.ts.map +1 -1
  118. package/dist/types/src/capabilities/react-root.d.ts +2 -2
  119. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  120. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  121. package/dist/types/src/capabilities/settings.d.ts +1 -1
  122. package/dist/types/src/capabilities/state.d.ts +2 -2
  123. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  124. package/dist/types/src/capabilities/toolkit.d.ts +6 -0
  125. package/dist/types/src/capabilities/toolkit.d.ts.map +1 -0
  126. package/dist/types/src/components/Call/Call.d.ts.map +1 -1
  127. package/dist/types/src/components/Call/Toolbar.d.ts.map +1 -1
  128. package/dist/types/src/components/CallDebugPanel.d.ts +7 -0
  129. package/dist/types/src/components/CallDebugPanel.d.ts.map +1 -1
  130. package/dist/types/src/components/CallSidebar.d.ts.map +1 -1
  131. package/dist/types/src/components/ChannelContainer.d.ts.map +1 -1
  132. package/dist/types/src/components/ChannelContainer.stories.d.ts +89 -5
  133. package/dist/types/src/components/ChannelContainer.stories.d.ts.map +1 -1
  134. package/dist/types/src/components/Chat.stories.d.ts +91 -5
  135. package/dist/types/src/components/Chat.stories.d.ts.map +1 -1
  136. package/dist/types/src/components/ChatContainer.d.ts.map +1 -1
  137. package/dist/types/src/components/Comments.stories.d.ts +160 -4
  138. package/dist/types/src/components/Comments.stories.d.ts.map +1 -1
  139. package/dist/types/src/components/CommentsContainer.d.ts.map +1 -1
  140. package/dist/types/src/components/CommentsThreadContainer.d.ts +2 -2
  141. package/dist/types/src/components/CommentsThreadContainer.d.ts.map +1 -1
  142. package/dist/types/src/components/Lobby/Lobby.d.ts.map +1 -1
  143. package/dist/types/src/components/Media/VideoObject.d.ts +2 -2
  144. package/dist/types/src/components/Media/VideoObject.d.ts.map +1 -1
  145. package/dist/types/src/components/Media/VideoObject.stories.d.ts +18 -4
  146. package/dist/types/src/components/Media/VideoObject.stories.d.ts.map +1 -1
  147. package/dist/types/src/components/MessageContainer.d.ts +4 -1
  148. package/dist/types/src/components/MessageContainer.d.ts.map +1 -1
  149. package/dist/types/src/components/Participant/Participant.d.ts.map +1 -1
  150. package/dist/types/src/components/Participant/ParticipantGrid.d.ts.map +1 -1
  151. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts +155 -3
  152. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts.map +1 -1
  153. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts +157 -4
  154. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts.map +1 -1
  155. package/dist/types/src/components/ResponsiveGrid/ResponsiveGridItem.d.ts.map +1 -1
  156. package/dist/types/src/components/ThreadComplementary.d.ts.map +1 -1
  157. package/dist/types/src/components/ThreadSettings.d.ts +1 -1
  158. package/dist/types/src/components/ThreadSettings.d.ts.map +1 -1
  159. package/dist/types/src/components/command-extension.d.ts.map +1 -1
  160. package/dist/types/src/components/testing.d.ts +1 -0
  161. package/dist/types/src/components/testing.d.ts.map +1 -1
  162. package/dist/types/src/extensions/threads.d.ts.map +1 -1
  163. package/dist/types/src/hooks/index.d.ts +1 -0
  164. package/dist/types/src/hooks/index.d.ts.map +1 -1
  165. package/dist/types/src/hooks/useBlackCanvasStreamTrack.d.ts +2 -0
  166. package/dist/types/src/hooks/useBlackCanvasStreamTrack.d.ts.map +1 -0
  167. package/dist/types/src/hooks/useVideoStreamTrack.d.ts +1 -1
  168. package/dist/types/src/hooks/useVideoStreamTrack.d.ts.map +1 -1
  169. package/dist/types/src/meta.d.ts +1 -2
  170. package/dist/types/src/meta.d.ts.map +1 -1
  171. package/dist/types/src/translations.d.ts +3 -1
  172. package/dist/types/src/translations.d.ts.map +1 -1
  173. package/dist/types/src/types/schema.d.ts +126 -109
  174. package/dist/types/src/types/schema.d.ts.map +1 -1
  175. package/dist/types/src/types/types.d.ts +259 -172
  176. package/dist/types/src/types/types.d.ts.map +1 -1
  177. package/dist/types/tsconfig.tsbuildinfo +1 -1
  178. package/package.json +64 -62
  179. package/src/ThreadPlugin.tsx +130 -124
  180. package/src/calls/call-manager.ts +2 -2
  181. package/src/calls/call-swarm-synchronizer.ts +1 -1
  182. package/src/calls/media-manager.ts +60 -34
  183. package/src/calls/types.ts +8 -4
  184. package/src/calls/util/calls-service.ts +65 -14
  185. package/src/calls/util/stub-media-streams.ts +62 -5
  186. package/src/calls-service.stories.tsx +78 -65
  187. package/src/capabilities/app-graph-builder.ts +18 -14
  188. package/src/capabilities/call-manager.ts +3 -2
  189. package/src/capabilities/capabilities.ts +7 -7
  190. package/src/capabilities/index.ts +1 -0
  191. package/src/capabilities/intent-resolver.ts +43 -9
  192. package/src/capabilities/markdown.ts +4 -3
  193. package/src/capabilities/react-root.tsx +2 -2
  194. package/src/capabilities/react-surface.tsx +14 -13
  195. package/src/capabilities/state.ts +2 -1
  196. package/src/capabilities/toolkit.ts +82 -0
  197. package/src/components/Call/Call.tsx +3 -2
  198. package/src/components/Call/Toolbar.tsx +5 -5
  199. package/src/components/CallDebugPanel.tsx +108 -49
  200. package/src/components/CallSidebar.tsx +2 -1
  201. package/src/components/ChannelContainer.stories.tsx +11 -10
  202. package/src/components/ChannelContainer.tsx +8 -7
  203. package/src/components/Chat.stories.tsx +34 -31
  204. package/src/components/ChatContainer.tsx +8 -4
  205. package/src/components/Comments.stories.tsx +39 -38
  206. package/src/components/CommentsContainer.tsx +2 -1
  207. package/src/components/CommentsThreadContainer.tsx +9 -7
  208. package/src/components/Lobby/Lobby.tsx +1 -1
  209. package/src/components/Media/VideoObject.stories.tsx +36 -28
  210. package/src/components/MessageContainer.tsx +43 -9
  211. package/src/components/Participant/Participant.tsx +13 -7
  212. package/src/components/Participant/ParticipantGrid.tsx +2 -1
  213. package/src/components/ResponsiveGrid/ResponsiveContainer.stories.tsx +8 -8
  214. package/src/components/ResponsiveGrid/ResponsiveGrid.stories.tsx +44 -42
  215. package/src/components/ResponsiveGrid/ResponsiveGrid.tsx +1 -1
  216. package/src/components/ResponsiveGrid/ResponsiveGridItem.tsx +2 -2
  217. package/src/components/ThreadComplementary.tsx +37 -7
  218. package/src/components/ThreadSettings.tsx +6 -7
  219. package/src/components/command-extension.ts +5 -2
  220. package/src/components/testing.ts +22 -0
  221. package/src/extensions/threads.ts +3 -3
  222. package/src/hooks/index.ts +1 -0
  223. package/src/hooks/useBlackCanvasStreamTrack.tsx +27 -0
  224. package/src/hooks/useDebugMode.ts +1 -1
  225. package/src/hooks/useVideoStreamTrack.tsx +6 -3
  226. package/src/meta.ts +3 -4
  227. package/src/testing/stories.ts +3 -3
  228. package/src/translations.ts +3 -1
  229. package/src/types/schema.ts +1 -1
  230. package/src/types/types.ts +22 -13
  231. package/src/typings/peermetrics-webrtc-stats.d.ts +17 -1
  232. package/src/typings.d.ts +8 -0
  233. package/src/util.ts +1 -1
  234. package/dist/lib/browser/ChannelContainer-3GIE7ASU.mjs +0 -16
  235. package/dist/lib/browser/ChatContainer-AIGIWAUG.mjs +0 -15
  236. package/dist/lib/browser/app-graph-builder-N7BE5TYW.mjs.map +0 -7
  237. package/dist/lib/browser/call-manager-NIPDYUVD.mjs.map +0 -7
  238. package/dist/lib/browser/chunk-3SGRT4NM.mjs +0 -367
  239. package/dist/lib/browser/chunk-3SGRT4NM.mjs.map +0 -7
  240. package/dist/lib/browser/chunk-6NSMBO3B.mjs.map +0 -7
  241. package/dist/lib/browser/chunk-ERWASUQK.mjs.map +0 -7
  242. package/dist/lib/browser/chunk-EV4JWI7L.mjs.map +0 -7
  243. package/dist/lib/browser/chunk-FR7KJPNY.mjs +0 -21
  244. package/dist/lib/browser/chunk-GCLD5ESP.mjs.map +0 -7
  245. package/dist/lib/browser/chunk-GERVMFQW.mjs.map +0 -7
  246. package/dist/lib/browser/chunk-KWPRNHTK.mjs.map +0 -7
  247. package/dist/lib/browser/chunk-LGSDKXPF.mjs +0 -18
  248. package/dist/lib/browser/chunk-LGSDKXPF.mjs.map +0 -7
  249. package/dist/lib/browser/chunk-VUWC4IJM.mjs +0 -479
  250. package/dist/lib/browser/chunk-VUWC4IJM.mjs.map +0 -7
  251. package/dist/lib/browser/chunk-ZE7KWN36.mjs.map +0 -7
  252. package/dist/lib/browser/intent-resolver-JFGLZ6VI.mjs.map +0 -7
  253. package/dist/lib/browser/markdown-M3FMR7OD.mjs.map +0 -7
  254. package/dist/lib/browser/react-root-JEUSQXI6.mjs +0 -28
  255. package/dist/lib/browser/react-root-JEUSQXI6.mjs.map +0 -7
  256. package/dist/lib/browser/react-surface-XWS6GIZY.mjs.map +0 -7
  257. package/dist/lib/browser/state-H6CYONWE.mjs.map +0 -7
  258. package/dist/lib/node-esm/ChannelContainer-7FXCKO7X.mjs +0 -17
  259. package/dist/lib/node-esm/app-graph-builder-VCW76Z6V.mjs.map +0 -7
  260. package/dist/lib/node-esm/call-manager-D6O5ZJJ4.mjs.map +0 -7
  261. package/dist/lib/node-esm/chunk-2CXOK2TD.mjs +0 -23
  262. package/dist/lib/node-esm/chunk-2MFNK53T.mjs +0 -480
  263. package/dist/lib/node-esm/chunk-2MFNK53T.mjs.map +0 -7
  264. package/dist/lib/node-esm/chunk-57XR3LEF.mjs.map +0 -7
  265. package/dist/lib/node-esm/chunk-75RJ5DJI.mjs +0 -19
  266. package/dist/lib/node-esm/chunk-75RJ5DJI.mjs.map +0 -7
  267. package/dist/lib/node-esm/chunk-C3XFMUAY.mjs.map +0 -7
  268. package/dist/lib/node-esm/chunk-FLBFYGBK.mjs +0 -368
  269. package/dist/lib/node-esm/chunk-FLBFYGBK.mjs.map +0 -7
  270. package/dist/lib/node-esm/chunk-GRLRWTRU.mjs.map +0 -7
  271. package/dist/lib/node-esm/chunk-IHDNQLLR.mjs.map +0 -7
  272. package/dist/lib/node-esm/chunk-OU5BYIDO.mjs.map +0 -7
  273. package/dist/lib/node-esm/chunk-TDFHTCZZ.mjs.map +0 -7
  274. package/dist/lib/node-esm/intent-resolver-OXGNQ44Y.mjs.map +0 -7
  275. package/dist/lib/node-esm/markdown-INKTE4MH.mjs.map +0 -7
  276. package/dist/lib/node-esm/react-root-XYYY2JXZ.mjs +0 -29
  277. package/dist/lib/node-esm/react-root-XYYY2JXZ.mjs.map +0 -7
  278. package/dist/lib/node-esm/react-surface-MJ33KPYE.mjs.map +0 -7
  279. package/dist/lib/node-esm/state-D7WNDT3N.mjs.map +0 -7
  280. /package/dist/lib/browser/{ChannelContainer-3GIE7ASU.mjs.map → ChannelContainer-BGDGZHV4.mjs.map} +0 -0
  281. /package/dist/lib/browser/{ChatContainer-AIGIWAUG.mjs.map → ChatContainer-75KJZ4XR.mjs.map} +0 -0
  282. /package/dist/lib/node-esm/{ChannelContainer-7FXCKO7X.mjs.map → ChannelContainer-OXC6BTU7.mjs.map} +0 -0
  283. /package/dist/lib/node-esm/{ChatContainer-IQUWU426.mjs.map → ChatContainer-SH6LTFQL.mjs.map} +0 -0
@@ -9,27 +9,37 @@ import { Surface } from '@dxos/app-framework';
9
9
  import { type Obj, Ref, type Type } from '@dxos/echo';
10
10
  import { PublicKey } from '@dxos/react-client';
11
11
  import { type SpaceMember } from '@dxos/react-client/echo';
12
- import { useIdentity, type Identity } from '@dxos/react-client/halo';
12
+ import { type Identity, useIdentity } from '@dxos/react-client/halo';
13
13
  import { IconButton, useOnTransition, useThemeContext, useTranslation } from '@dxos/react-ui';
14
14
  import { createBasicExtensions, createThemeExtensions, useTextEditor } from '@dxos/react-ui-editor';
15
15
  import { hoverableControlItem, hoverableControls, hoverableFocusedWithinControls, mx } from '@dxos/react-ui-theme';
16
16
  import { MessageHeading, MessageRoot } from '@dxos/react-ui-thread';
17
17
  import { type DataType } from '@dxos/schema';
18
18
 
19
- import { commentControlClassNames } from './CommentsThreadContainer';
20
- import { command } from './command-extension';
21
19
  import { useOnEditAnalytics } from '../hooks';
22
20
  import { meta } from '../meta';
23
21
  import { getMessageMetadata } from '../util';
24
22
 
23
+ import { command } from './command-extension';
24
+
25
+ export const buttonGroupClassNames = 'flex flex-row items-center gap-0.5 pie-2';
26
+ export const buttonClassNames = '!p-1 transition-opacity';
27
+
25
28
  export type MessageContainerProps = {
26
29
  message: DataType.Message;
27
30
  members: SpaceMember[];
28
31
  editable?: boolean;
29
32
  onDelete?: (id: string) => void;
33
+ onAcceptProposal?: (id: string) => void;
30
34
  };
31
35
 
32
- export const MessageContainer = ({ message, members, editable = false, onDelete }: MessageContainerProps) => {
36
+ export const MessageContainer = ({
37
+ message,
38
+ members,
39
+ editable = false,
40
+ onDelete,
41
+ onAcceptProposal,
42
+ }: MessageContainerProps) => {
33
43
  const { t } = useTranslation(meta.id);
34
44
  const senderIdentity = members.find(
35
45
  (member) =>
@@ -39,8 +49,11 @@ export const MessageContainer = ({ message, members, editable = false, onDelete
39
49
  const messageMetadata = getMessageMetadata(message.id, senderIdentity);
40
50
  const userIsAuthor = useIdentity()?.did === messageMetadata.authorId;
41
51
  const [editing, setEditing] = useState(false);
52
+ const handleEdit = useCallback(() => setEditing((editing) => !editing), []);
42
53
  const handleDelete = useCallback(() => onDelete?.(message.id), [message, onDelete]);
54
+ const handleAcceptProposal = useCallback(() => onAcceptProposal?.(message.id), [message, onAcceptProposal]);
43
55
  const textBlock = message.blocks.find((block) => block._tag === 'text');
56
+ const proposalBlock = message.blocks.find((block) => block._tag === 'proposal');
44
57
  const references = message.blocks.filter((block) => block._tag === 'reference').map((block) => block.reference);
45
58
 
46
59
  useOnEditAnalytics(message, textBlock, !!editing);
@@ -48,7 +61,7 @@ export const MessageContainer = ({ message, members, editable = false, onDelete
48
61
  return (
49
62
  <MessageRoot {...messageMetadata} classNames={[hoverableControls, hoverableFocusedWithinControls]}>
50
63
  <MessageHeading authorName={messageMetadata.authorName} timestamp={messageMetadata.timestamp}>
51
- <div className='flex flex-row items-center gap-0.5'>
64
+ <div role='none' className={buttonGroupClassNames}>
52
65
  {userIsAuthor && editable && (
53
66
  <IconButton
54
67
  data-testid={editing ? 'thread.message.save' : 'thread.message.edit'}
@@ -56,8 +69,20 @@ export const MessageContainer = ({ message, members, editable = false, onDelete
56
69
  icon={editing ? 'ph--check--regular' : 'ph--pencil-simple--regular'}
57
70
  iconOnly
58
71
  label={t(editing ? 'save message label' : 'edit message label')}
59
- classNames={[commentControlClassNames, hoverableControlItem]}
60
- onClick={() => setEditing((editing) => !editing)}
72
+ classNames={[buttonClassNames, hoverableControlItem]}
73
+ onClick={handleEdit}
74
+ />
75
+ )}
76
+ {/* TODO(wittjosiah): Proposal controls should probably be hoisted to thread level. */}
77
+ {proposalBlock && onAcceptProposal && (
78
+ <IconButton
79
+ data-testid='thread.message.accept'
80
+ variant='ghost'
81
+ icon='ph--check--regular'
82
+ iconOnly
83
+ label={t('accept proposal label')}
84
+ classNames={[buttonClassNames, hoverableControlItem]}
85
+ onClick={handleAcceptProposal}
61
86
  />
62
87
  )}
63
88
  {onDelete && (
@@ -67,13 +92,14 @@ export const MessageContainer = ({ message, members, editable = false, onDelete
67
92
  icon='ph--x--regular'
68
93
  iconOnly
69
94
  label={t('delete message label')}
70
- classNames={[commentControlClassNames, hoverableControlItem]}
71
- onClick={() => handleDelete()}
95
+ classNames={[buttonClassNames, hoverableControlItem]}
96
+ onClick={handleDelete}
72
97
  />
73
98
  )}
74
99
  </div>
75
100
  </MessageHeading>
76
101
  {textBlock && <TextboxBlock block={textBlock} isAuthor={userIsAuthor} editing={editing} />}
102
+ {proposalBlock && <ProposalBlock block={proposalBlock} />}
77
103
  {Ref.Array.targets(references).map((reference, index) => (
78
104
  <MessagePart key={index} part={reference} />
79
105
  ))}
@@ -132,6 +158,14 @@ const TextboxBlock = ({
132
158
  return <div role='none' ref={parentRef} className='mie-4' {...focusAttributes} />;
133
159
  };
134
160
 
161
+ const ProposalBlock = ({ block }: { block: DataType.MessageBlock.Proposal }) => {
162
+ return (
163
+ <div role='none' className='mie-4 italic'>
164
+ {block.text}
165
+ </div>
166
+ );
167
+ };
168
+
135
169
  const MessageBlockObjectTile = forwardRef<HTMLDivElement, { subject: Obj.Any }>(({ subject }, forwardedRef) => {
136
170
  // TODO(burdon): Use annotation to get title.
137
171
  let title = (subject as any).name ?? (subject as any).title ?? (subject as any).type ?? 'Object';
@@ -17,15 +17,21 @@ export const Participant = memo(({ item: user, debug, ...props }: ResponsiveGrid
17
17
  const call = useCapability(ThreadCapabilities.CallManager);
18
18
  const isSelf: boolean = call.self.id !== undefined && user.id !== undefined && user.id.startsWith(call.self.id);
19
19
  const isScreenshare = user.id?.endsWith(SCREENSHARE_SUFFIX);
20
- const pulledVideoStream = call.getVideoStream(
21
- isScreenshare || !isSelf ? (user.tracks?.video as EncodedTrackName) : undefined,
22
- );
20
+
21
+ const pulledVideoStream =
22
+ !isSelf && isScreenshare && user.tracks?.screenshareEnabled
23
+ ? call.getVideoStream(user.tracks?.screenshare as EncodedTrackName)
24
+ : !isSelf && !isScreenshare && user.tracks?.videoEnabled
25
+ ? call.getVideoStream(user.tracks?.video as EncodedTrackName)
26
+ : undefined;
23
27
 
24
28
  const videoStream = useMemo<MediaStream | undefined>(() => {
25
- if (isSelf && !isScreenshare) {
26
- return call.media.videoStream;
27
- } else if (isSelf && isScreenshare) {
28
- return call.media.screenshareVideoStream;
29
+ if (isSelf) {
30
+ if (isScreenshare) {
31
+ return call.media.screenshareVideoStream;
32
+ } else if (!isScreenshare) {
33
+ return call.media.videoStream;
34
+ }
29
35
  } else if (!isSelf) {
30
36
  return pulledVideoStream;
31
37
  }
@@ -6,10 +6,11 @@ import React, { useEffect, useMemo, useState } from 'react';
6
6
 
7
7
  import { type ThemedClassName } from '@dxos/react-ui';
8
8
 
9
- import { Participant, SCREENSHARE_SUFFIX } from './Participant';
10
9
  import { type UserState } from '../../calls';
11
10
  import { ResponsiveGrid } from '../ResponsiveGrid';
12
11
 
12
+ import { Participant, SCREENSHARE_SUFFIX } from './Participant';
13
+
13
14
  const getId = (user: UserState): string => user.id!;
14
15
 
15
16
  export type ParticipantGridProps = ThemedClassName<{
@@ -2,25 +2,25 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
- import { type StoryObj, type Meta } from '@storybook/react-vite';
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
8
6
  import React from 'react';
9
7
 
10
- import { withTheme, withLayout } from '@dxos/storybook-utils';
8
+ import { withTheme } from '@dxos/react-ui/testing';
11
9
 
12
- import { ResponsiveContainer } from './ResponsiveContainer';
13
10
  import { translations } from '../../translations';
14
11
  import { VideoObject as VideoObjectComponent } from '../Media';
15
12
 
16
- const meta: Meta<typeof ResponsiveContainer> = {
13
+ import { ResponsiveContainer } from './ResponsiveContainer';
14
+
15
+ const meta = {
17
16
  title: 'plugins/plugin-thread/ResponsiveContainer',
18
17
  component: ResponsiveContainer,
19
- decorators: [withTheme, withLayout({ fullscreen: true })],
18
+ decorators: [withTheme],
20
19
  parameters: {
20
+ layout: 'fullscreen',
21
21
  translations,
22
22
  },
23
- };
23
+ } satisfies Meta<typeof ResponsiveContainer>;
24
24
 
25
25
  export default meta;
26
26
 
@@ -2,17 +2,16 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
- import { type StoryObj, type Meta } from '@storybook/react-vite';
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
8
6
  import React, { useEffect, useState } from 'react';
9
7
 
10
8
  import { faker } from '@dxos/random';
11
- import { withTheme, withLayout } from '@dxos/storybook-utils';
9
+ import { withTheme } from '@dxos/react-ui/testing';
10
+
11
+ import { translations } from '../../translations';
12
12
 
13
13
  import { ResponsiveGrid, type ResponsiveGridProps } from './ResponsiveGrid';
14
14
  import { ResponsiveGridItem, type ResponsiveGridItemProps } from './ResponsiveGridItem';
15
- import { translations } from '../../translations';
16
15
 
17
16
  type TestItem = {
18
17
  id: string;
@@ -56,46 +55,49 @@ const TestCell = ({ item, ...props }: ResponsiveGridItemProps<TestItem>) => {
56
55
 
57
56
  type StoryProps = ResponsiveGridProps<TestItem> & { random?: boolean; autoHideGallery?: boolean };
58
57
 
59
- const meta: Meta<StoryProps> = {
58
+ const DefaultStory = (props: StoryProps) => {
59
+ const [pinned, setPinned] = useState<string | undefined>(
60
+ (props.pinned ?? props.items.length > 1) ? props.items[0]?.id : undefined,
61
+ );
62
+ const [items, setItems] = useState<TestItem[]>(props.items);
63
+ useEffect(() => {
64
+ if (!props.random) {
65
+ return;
66
+ }
67
+
68
+ const interval = setInterval(() => {
69
+ setItems((items) => {
70
+ const p = Math.random();
71
+ if (p < 0.5) {
72
+ return items;
73
+ } else if (p < 0.99 && items.length > 1) {
74
+ return items.slice(0, -1);
75
+ } else {
76
+ return [...items, createItem(items[0]?.type)];
77
+ }
78
+ });
79
+ }, 3_000);
80
+
81
+ return () => clearInterval(interval);
82
+ }, []);
83
+
84
+ return (
85
+ <div className='grid grow p-4'>
86
+ <ResponsiveGrid {...props} Cell={TestCell} items={items} pinned={pinned} onPinnedChange={setPinned} />
87
+ </div>
88
+ );
89
+ };
90
+
91
+ const meta = {
60
92
  title: 'plugins/plugin-thread/ResponsiveGrid',
61
- component: ResponsiveGrid,
62
- render: (args) => {
63
- const [pinned, setPinned] = useState<string | undefined>(
64
- (args.pinned ?? args.items.length > 1) ? args.items[0]?.id : undefined,
65
- );
66
- const [items, setItems] = useState<TestItem[]>(args.items);
67
- useEffect(() => {
68
- if (!args.random) {
69
- return;
70
- }
71
-
72
- const interval = setInterval(() => {
73
- setItems((items) => {
74
- const p = Math.random();
75
- if (p < 0.5) {
76
- return items;
77
- } else if (p < 0.99 && items.length > 1) {
78
- return items.slice(0, -1);
79
- } else {
80
- return [...items, createItem(items[0]?.type)];
81
- }
82
- });
83
- }, 3_000);
84
-
85
- return () => clearInterval(interval);
86
- }, []);
87
-
88
- return (
89
- <div className='grid grow p-4'>
90
- <ResponsiveGrid {...args} Cell={TestCell} items={items} pinned={pinned} onPinnedChange={setPinned} />
91
- </div>
92
- );
93
- },
94
- decorators: [withTheme, withLayout({ fullscreen: true, classNames: 'justify-center' })],
93
+ component: ResponsiveGrid as any,
94
+ render: DefaultStory,
95
+ decorators: [withTheme],
95
96
  parameters: {
97
+ layout: 'fullscreen',
96
98
  translations,
97
99
  },
98
- };
100
+ } satisfies Meta<typeof DefaultStory>;
99
101
 
100
102
  const videoUrls = [
101
103
  'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4',
@@ -117,7 +119,7 @@ const createItem = (type?: 'image' | 'video') => {
117
119
 
118
120
  export default meta;
119
121
 
120
- type Story = StoryObj<StoryProps>;
122
+ type Story = StoryObj<typeof meta>;
121
123
 
122
124
  // TODO(burdon): Story to join/leave repeatedly to test stable position.
123
125
 
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import React, { type ComponentType, type FC, useLayoutEffect, useState, useEffect, useMemo, useCallback } from 'react';
5
+ import React, { type ComponentType, type FC, useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';
6
6
  import { useResizeDetector } from 'react-resize-detector';
7
7
 
8
8
  import { invariant } from '@dxos/invariant';
@@ -2,9 +2,9 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import React, { useEffect, useState, type CSSProperties, type PropsWithChildren } from 'react';
5
+ import React, { type CSSProperties, type PropsWithChildren, useEffect, useState } from 'react';
6
6
 
7
- import { Icon, IconButton, useTranslation, type ThemedClassName } from '@dxos/react-ui';
7
+ import { Icon, IconButton, type ThemedClassName, useTranslation } from '@dxos/react-ui';
8
8
  import { Waveform } from '@dxos/react-ui-sfx';
9
9
  import { groupHoverControlItemWithTransition, mx } from '@dxos/react-ui-theme';
10
10
 
@@ -6,23 +6,25 @@ import React, { useCallback, useMemo } from 'react';
6
6
 
7
7
  import {
8
8
  Capabilities,
9
+ CollaborationActions,
9
10
  LayoutAction,
10
11
  createIntent,
11
- useCapability,
12
12
  useCapabilities,
13
+ useCapability,
13
14
  useIntentDispatcher,
14
15
  } from '@dxos/app-framework';
15
16
  import { Filter, Obj, Query, Relation } from '@dxos/echo';
16
- import { fullyQualifiedId, getSpace, useQuery } from '@dxos/react-client/echo';
17
+ import { Ref, fullyQualifiedId, getSpace, useQuery } from '@dxos/react-client/echo';
17
18
  import { useIdentity } from '@dxos/react-client/halo';
18
19
  import { useThemeContext, useTranslation } from '@dxos/react-ui';
19
20
  import { useAttended } from '@dxos/react-ui-attention';
20
21
  import { StackItem } from '@dxos/react-ui-stack';
21
22
  import { Tabs } from '@dxos/react-ui-tabs';
23
+ import { mx } from '@dxos/react-ui-theme';
22
24
  import { AnchoredTo } from '@dxos/schema';
23
25
 
24
26
  import { ThreadCapabilities } from '../capabilities';
25
- import { CommentsContainer } from '../components';
27
+ import { CommentsContainer, type CommentsContainerProps } from '../components';
26
28
  import { meta } from '../meta';
27
29
  import { ThreadAction, ThreadType } from '../types';
28
30
 
@@ -114,6 +116,28 @@ export const ThreadComplementary = ({ subject }: { subject: any }) => {
114
116
  [dispatch, subject],
115
117
  );
116
118
 
119
+ const handleAcceptProposal = useCallback<NonNullable<CommentsContainerProps['onAcceptProposal']>>(
120
+ async (anchor, messageId) => {
121
+ const thread = Relation.getSource(anchor) as ThreadType;
122
+ const messageIndex = thread.messages.findIndex(Ref.hasObjectId(messageId));
123
+ const message = thread.messages[messageIndex]?.target;
124
+ const proposal = message?.blocks.find((block) => block._tag === 'proposal');
125
+ if (!proposal || !anchor.anchor) {
126
+ return;
127
+ }
128
+
129
+ await dispatch(
130
+ createIntent(CollaborationActions.AcceptProposal, {
131
+ subject,
132
+ anchor: anchor.anchor,
133
+ proposal,
134
+ }),
135
+ );
136
+ await dispatch(createIntent(ThreadAction.ToggleResolved, { thread }));
137
+ },
138
+ [dispatch, subject],
139
+ );
140
+
117
141
  const comments = (
118
142
  <CommentsContainer
119
143
  anchors={anchors}
@@ -124,6 +148,7 @@ export const ThreadComplementary = ({ subject }: { subject: any }) => {
124
148
  onResolve={handleResolve}
125
149
  onMessageDelete={handleMessageDelete}
126
150
  onThreadDelete={handleThreadDelete}
151
+ onAcceptProposal={handleAcceptProposal}
127
152
  />
128
153
  );
129
154
 
@@ -132,10 +157,13 @@ export const ThreadComplementary = ({ subject }: { subject: any }) => {
132
157
  <Tabs.Root
133
158
  value={showResolvedThreads ? 'all' : 'unresolved'}
134
159
  orientation='horizontal'
135
- classNames='contents [&_[role="tabpanel"]]:min-bs-0 [&_[role="tabpanel"]]:overflow-y-auto [&_[role="tabpanel"]]:scrollbar-thin'
160
+ classNames={[
161
+ 'contents [&_[role="tabpanel"]]:min-bs-0 [&_[role="tabpanel"]]:overflow-y-auto [&_[role="tabpanel"]]:scrollbar-thin',
162
+ ]}
136
163
  onValueChange={onChangeViewState}
137
164
  >
138
- <Tabs.Tablist classNames={tx('toolbar.root', 'toolbar', {})}>
165
+ {/* TODO(burdon): Standardize (like Tollbar). */}
166
+ <Tabs.Tablist classNames={mx('bg-toolbarSurface border-b border-subduedSeparator')}>
139
167
  <Tabs.Tab value='unresolved' classNames='text-sm'>
140
168
  {t('show unresolved label')}
141
169
  </Tabs.Tab>
@@ -143,8 +171,10 @@ export const ThreadComplementary = ({ subject }: { subject: any }) => {
143
171
  {t('show all label')}
144
172
  </Tabs.Tab>
145
173
  </Tabs.Tablist>
146
- <Tabs.Tabpanel value='all'>{showResolvedThreads && comments}</Tabs.Tabpanel>
147
- <Tabs.Tabpanel value='unresolved'>{!showResolvedThreads && comments}</Tabs.Tabpanel>
174
+ <div className='overflow-y-auto'>
175
+ <Tabs.Tabpanel value='all'>{showResolvedThreads && comments}</Tabs.Tabpanel>
176
+ <Tabs.Tabpanel value='unresolved'>{!showResolvedThreads && comments}</Tabs.Tabpanel>
177
+ </div>
148
178
  </Tabs.Root>
149
179
  </StackItem.Content>
150
180
  );
@@ -4,14 +4,13 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- // import { useTranslation } from '@dxos/react-ui';
8
- import { DeprecatedFormContainer } from '@dxos/react-ui-form';
7
+ import { useTranslation } from '@dxos/react-ui';
8
+ import { ControlPage } from '@dxos/react-ui-form';
9
9
 
10
- // import { meta } from '../meta';
10
+ import { meta } from '../meta';
11
11
  import type { ThreadSettingsProps } from '../types';
12
12
 
13
- export const ThreadSettings = ({ settings }: { settings: ThreadSettingsProps }) => {
14
- // const { t } = useTranslation(meta.id);
15
-
16
- return <DeprecatedFormContainer></DeprecatedFormContainer>;
13
+ export const ThreadSettings = ({ settings: _settings }: { settings: ThreadSettingsProps }) => {
14
+ const { t: _t } = useTranslation(meta.id);
15
+ return <ControlPage></ControlPage>;
17
16
  };
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { StreamLanguage, HighlightStyle, syntaxHighlighting } from '@codemirror/language';
5
+ import { HighlightStyle, StreamLanguage, syntaxHighlighting } from '@codemirror/language';
6
6
  import { type Extension } from '@codemirror/state';
7
7
 
8
8
  import { tags } from '@dxos/react-ui-editor';
@@ -27,7 +27,10 @@ const parser = StreamLanguage.define<{ count: number }>({
27
27
  });
28
28
 
29
29
  const styles = HighlightStyle.define([
30
- { tag: tags.tagName, class: mx('dx-tag dx-tag--indigo text-baseText font-medium') },
30
+ {
31
+ tag: tags.tagName,
32
+ class: mx('dx-tag dx-tag--indigo text-baseText font-medium'),
33
+ },
31
34
  ]);
32
35
 
33
36
  export const command: Extension = [parser, syntaxHighlighting(styles)];
@@ -12,6 +12,7 @@ import { ThreadType } from '../types';
12
12
 
13
13
  export const createCommentThread = (identity: Identity): ThreadType => {
14
14
  return Obj.make(ThreadType, {
15
+ name: 'Comment',
15
16
  messages: faker.helpers.multiple(
16
17
  () =>
17
18
  Ref.make(
@@ -25,5 +26,26 @@ export const createCommentThread = (identity: Identity): ThreadType => {
25
26
  ),
26
27
  { count: { min: 2, max: 3 } },
27
28
  ),
29
+ status: 'active',
30
+ });
31
+ };
32
+
33
+ export const createProposalThread = (identity: Identity): ThreadType => {
34
+ return Obj.make(ThreadType, {
35
+ name: 'Proposal',
36
+ messages: faker.helpers.multiple(
37
+ () =>
38
+ Ref.make(
39
+ Obj.make(DataType.Message, {
40
+ created: new Date().toISOString(),
41
+ sender: {
42
+ identityDid: faker.datatype.boolean() ? identity.did : IdentityDid.random(),
43
+ },
44
+ blocks: [{ _tag: 'proposal', text: faker.lorem.sentences(3) }],
45
+ }),
46
+ ),
47
+ { count: { min: 1, max: 1 } },
48
+ ),
49
+ status: 'active',
28
50
  });
29
51
  };
@@ -6,14 +6,14 @@ import { type Extension } from '@codemirror/state';
6
6
  import { EditorView } from '@codemirror/view';
7
7
  import { computed, effect } from '@preact/signals-core';
8
8
 
9
- import { createIntent, type PromiseIntentDispatcher } from '@dxos/app-framework';
9
+ import { type PromiseIntentDispatcher, createIntent } from '@dxos/app-framework';
10
10
  import { Filter, Obj, Query, Relation } from '@dxos/echo';
11
11
  import { type Markdown } from '@dxos/plugin-markdown/types';
12
- import { getSpace, getTextInRange, createDocAccessor, fullyQualifiedId, getSource } from '@dxos/react-client/echo';
12
+ import { createDocAccessor, fullyQualifiedId, getSource, getSpace, getTextInRange } from '@dxos/react-client/echo';
13
13
  import { comments, createExternalCommentSync } from '@dxos/react-ui-editor';
14
14
  import { AnchoredTo } from '@dxos/schema';
15
15
 
16
- import { ThreadAction, ThreadType, type ThreadState } from '../types';
16
+ import { ThreadAction, type ThreadState, ThreadType } from '../types';
17
17
 
18
18
  // TODO(burdon): Factor out.
19
19
  const getName = (doc: Markdown.Document, anchor: string): string | undefined => {
@@ -7,3 +7,4 @@ export * from './useDebugMode';
7
7
  export * from './useStatus';
8
8
  export * from './useVideoStreamTrack';
9
9
  export * from './useInaudibleAudioStreamTrack';
10
+ export * from './useBlackCanvasStreamTrack';
@@ -0,0 +1,27 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { useEffect, useState } from 'react';
6
+
7
+ import { scheduleTask } from '@dxos/async';
8
+ import { Context } from '@dxos/context';
9
+
10
+ import { createBlackCanvasStreamTrack } from '../calls/util/stub-media-streams';
11
+
12
+ export const useBlackCanvasStreamTrack = () => {
13
+ const [blackCanvasStreamTrack, setBlackCanvasStreamTrack] = useState<MediaStreamTrack | undefined>(undefined);
14
+ useEffect(() => {
15
+ const ctx = new Context();
16
+ scheduleTask(ctx, async () => {
17
+ const blackCanvasStreamTrack = await createBlackCanvasStreamTrack({ ctx, width: 720, height: 480 });
18
+ setBlackCanvasStreamTrack(blackCanvasStreamTrack);
19
+ });
20
+
21
+ return () => {
22
+ void ctx.dispose();
23
+ };
24
+ }, []);
25
+
26
+ return blackCanvasStreamTrack;
27
+ };
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { useState, useEffect } from 'react';
5
+ import { useEffect, useState } from 'react';
6
6
 
7
7
  // TODO(burdon): Standardize across plugins/composer.
8
8
  export const useDebugMode = () => {
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { type RefObject, useEffect, useRef, useState } from 'react';
6
6
 
7
- export const useVideoStreamTrack = (videoElement: RefObject<HTMLVideoElement>, videoSrc: string) => {
7
+ export const useVideoStreamTrack = (videoElement: RefObject<HTMLVideoElement | null>, videoSrc: string) => {
8
8
  // Get video stream track.
9
9
  const [videoStreamTrack, setVideoStreamTrack] = useState<MediaStreamTrack | undefined>(undefined);
10
10
  const hadRun = useRef(false);
@@ -15,13 +15,16 @@ export const useVideoStreamTrack = (videoElement: RefObject<HTMLVideoElement>, v
15
15
  }
16
16
  hadRun.current = true;
17
17
  videoElement.current.addEventListener('playing', () => {
18
+ if (videoStreamTrack) {
19
+ return;
20
+ }
18
21
  const stream = (videoElement.current as any).captureStream();
19
22
  const track = stream.getTracks()[0];
20
- if (track) {
23
+ if (track && !videoStreamTrack) {
21
24
  setVideoStreamTrack(track);
22
25
  }
23
26
  stream.onaddtrack = (event: MediaStreamTrackEvent) => {
24
- if (event.track.kind === 'video') {
27
+ if (event.track.kind === 'video' && !videoStreamTrack) {
25
28
  setVideoStreamTrack(event.track);
26
29
  }
27
30
  };
package/src/meta.ts CHANGED
@@ -4,14 +4,13 @@
4
4
 
5
5
  import { type PluginMeta } from '@dxos/app-framework';
6
6
 
7
- export const THREAD_PLUGIN = 'dxos.org/plugin/thread';
8
- export const THREAD_ITEM = `${THREAD_PLUGIN}/item`;
9
-
10
7
  // TODO(wittjosiah): Needs screenshots.
11
8
  export const meta: PluginMeta = {
12
- id: THREAD_PLUGIN,
9
+ id: 'dxos.org/plugin/thread',
13
10
  name: 'Chat',
14
11
  description: 'Chat via text, voice, and video in channels or create comment threads on objects.',
15
12
  icon: 'ph--video-conference--regular',
16
13
  source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-thread',
17
14
  };
15
+
16
+ export const THREAD_ITEM = `${meta.id}/item`;
@@ -18,10 +18,10 @@ import { ChannelType, ThreadType } from '../types';
18
18
  export const createThreadPlugins = async () => [
19
19
  ThemePlugin({ tx: defaultTx }),
20
20
  ClientPlugin({
21
- onClientInitialized: async (_, client) => {
21
+ onClientInitialized: async ({ client }) => {
22
22
  await client.halo.createIdentity({ displayName: 'Test User' });
23
23
  },
24
- onSpacesReady: async (_, client) => {
24
+ onSpacesReady: async ({ client }) => {
25
25
  await client.spaces.default.waitUntilReady();
26
26
  const thread = Obj.make(ThreadType, { messages: [] });
27
27
  client.spaces.default.db.add(Obj.make(ChannelType, { defaultThread: Ref.make(thread), threads: [] }));
@@ -46,7 +46,7 @@ export const createThreadPlugins = async () => [
46
46
  },
47
47
  }),
48
48
  }),
49
- SpacePlugin(),
49
+ SpacePlugin({}),
50
50
  IntentPlugin(),
51
51
  SettingsPlugin(),
52
52
  GraphPlugin(),
@@ -44,6 +44,7 @@ export const translations = [
44
44
  'save message label': 'Save',
45
45
  'edit message label': 'Edit',
46
46
  'delete message label': 'Delete message',
47
+ 'accept proposal label': 'Accept proposal',
47
48
  'open comments panel label': 'Show Comments',
48
49
  'comments label': 'Comments',
49
50
  'show all label': 'All comments',
@@ -60,7 +61,8 @@ export const translations = [
60
61
  'call tab label': 'Call',
61
62
  'meeting status title': 'Meeting',
62
63
  'share meeting link label': 'Share meeting',
63
- 'show webrtc stats title': 'Detailed WebRTC Stats',
64
+ 'show webrtc stats title': 'WebRTC Stats',
65
+ 'show calls history title': 'Service History',
64
66
 
65
67
  'meeting summary label': 'Summary',
66
68
  'summarize label': 'Summarize',