@dxos/plugin-thread 0.8.2-main.fbd8ed0 → 0.8.2-staging.4d6ad0f

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 (385) hide show
  1. package/dist/lib/browser/ChannelContainer-XFNGSLHL.mjs +15 -0
  2. package/dist/lib/browser/ChatContainer-JWRI73OG.mjs +14 -0
  3. package/dist/lib/browser/app-graph-builder-K3CFBN7V.mjs +171 -0
  4. package/dist/lib/browser/app-graph-builder-K3CFBN7V.mjs.map +7 -0
  5. package/dist/lib/browser/call-manager-I4IKVCAK.mjs +23 -0
  6. package/dist/lib/browser/call-manager-I4IKVCAK.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-32EIWOAL.mjs → chunk-5P5BH5GE.mjs} +57 -35
  8. package/dist/lib/browser/chunk-5P5BH5GE.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-5PGLGDIP.mjs +983 -0
  10. package/dist/lib/browser/chunk-5PGLGDIP.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-G3TS64FP.mjs +351 -0
  12. package/dist/lib/browser/chunk-G3TS64FP.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-WBJLUUOK.mjs → chunk-IIUTBDVB.mjs} +4 -4
  14. package/dist/lib/browser/chunk-IIUTBDVB.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-IYY42OE2.mjs +545 -0
  16. package/dist/lib/browser/chunk-IYY42OE2.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-JKQUJOTX.mjs +31 -0
  18. package/dist/lib/browser/chunk-JKQUJOTX.mjs.map +7 -0
  19. package/dist/lib/browser/chunk-N2V6MV6B.mjs +21 -0
  20. package/dist/lib/browser/chunk-N2V6MV6B.mjs.map +7 -0
  21. package/dist/lib/browser/{chunk-EP6MRLY7.mjs → chunk-R5MDLUPC.mjs} +5 -3
  22. package/dist/lib/browser/chunk-R5MDLUPC.mjs.map +7 -0
  23. package/dist/lib/browser/chunk-RJGJXXWK.mjs +1708 -0
  24. package/dist/lib/browser/chunk-RJGJXXWK.mjs.map +7 -0
  25. package/dist/lib/browser/chunk-WDOQXTI2.mjs +126 -0
  26. package/dist/lib/browser/chunk-WDOQXTI2.mjs.map +7 -0
  27. package/dist/lib/browser/index.mjs +101 -35
  28. package/dist/lib/browser/index.mjs.map +4 -4
  29. package/dist/lib/browser/{intent-resolver-PDOLX5B7.mjs → intent-resolver-YUYZCTLF.mjs} +95 -62
  30. package/dist/lib/browser/intent-resolver-YUYZCTLF.mjs.map +7 -0
  31. package/dist/lib/browser/markdown-4EC3OCF2.mjs +169 -0
  32. package/dist/lib/browser/markdown-4EC3OCF2.mjs.map +7 -0
  33. package/dist/lib/browser/meta.json +1 -1
  34. package/dist/lib/browser/react-root-YYDCVHGL.mjs +27 -0
  35. package/dist/lib/browser/react-root-YYDCVHGL.mjs.map +7 -0
  36. package/dist/lib/browser/react-surface-MEYBFPBC.mjs +108 -0
  37. package/dist/lib/browser/react-surface-MEYBFPBC.mjs.map +7 -0
  38. package/dist/lib/browser/{settings-K56QXNJ4.mjs → settings-KVBQQSO5.mjs} +3 -3
  39. package/dist/lib/browser/{state-KBGI3QTR.mjs → state-RKL5MSDP.mjs} +4 -4
  40. package/dist/lib/browser/{state-KBGI3QTR.mjs.map → state-RKL5MSDP.mjs.map} +3 -3
  41. package/dist/lib/browser/types/index.mjs +16 -0
  42. package/dist/lib/browser/types/index.mjs.map +7 -0
  43. package/dist/lib/node/ChannelContainer-F24RHJPX.cjs +36 -0
  44. package/dist/lib/node/ChannelContainer-F24RHJPX.cjs.map +7 -0
  45. package/dist/lib/node/ChatContainer-EE3FPSYO.cjs +35 -0
  46. package/dist/lib/node/ChatContainer-EE3FPSYO.cjs.map +7 -0
  47. package/dist/lib/node/app-graph-builder-IRE3GYKE.cjs +179 -0
  48. package/dist/lib/node/app-graph-builder-IRE3GYKE.cjs.map +7 -0
  49. package/dist/lib/node/call-manager-FZ4OMTB6.cjs +37 -0
  50. package/dist/lib/node/call-manager-FZ4OMTB6.cjs.map +7 -0
  51. package/dist/lib/node/chunk-4B3PPXA6.cjs +371 -0
  52. package/dist/lib/node/chunk-4B3PPXA6.cjs.map +7 -0
  53. package/dist/lib/node/{chunk-NQ5DTPOY.cjs → chunk-4YSNVPWU.cjs} +10 -8
  54. package/dist/lib/node/chunk-4YSNVPWU.cjs.map +7 -0
  55. package/dist/lib/node/chunk-6B3M6XRE.cjs +984 -0
  56. package/dist/lib/node/chunk-6B3M6XRE.cjs.map +7 -0
  57. package/dist/lib/node/chunk-AUIU6JGD.cjs +549 -0
  58. package/dist/lib/node/chunk-AUIU6JGD.cjs.map +7 -0
  59. package/dist/lib/node/chunk-ECIVLX56.cjs +1731 -0
  60. package/dist/lib/node/chunk-ECIVLX56.cjs.map +7 -0
  61. package/dist/lib/node/{chunk-AZ275P4V.cjs → chunk-EYAUPLHT.cjs} +16 -10
  62. package/dist/lib/node/chunk-EYAUPLHT.cjs.map +7 -0
  63. package/dist/lib/node/{chunk-NO6WQR36.cjs → chunk-FUXJAVFZ.cjs} +50 -29
  64. package/dist/lib/node/chunk-FUXJAVFZ.cjs.map +7 -0
  65. package/dist/lib/node/{chunk-ONLWOUYZ.cjs → chunk-HLMCEE5K.cjs} +7 -7
  66. package/dist/lib/node/{chunk-ONLWOUYZ.cjs.map → chunk-HLMCEE5K.cjs.map} +2 -2
  67. package/dist/lib/node/chunk-LR5NENBE.cjs +54 -0
  68. package/dist/lib/node/chunk-LR5NENBE.cjs.map +7 -0
  69. package/dist/lib/node/chunk-TKHJVC2C.cjs +147 -0
  70. package/dist/lib/node/chunk-TKHJVC2C.cjs.map +7 -0
  71. package/dist/lib/node/index.cjs +136 -74
  72. package/dist/lib/node/index.cjs.map +4 -4
  73. package/dist/lib/node/{intent-resolver-MNTL32W2.cjs → intent-resolver-MZ3HADNY.cjs} +107 -76
  74. package/dist/lib/node/intent-resolver-MZ3HADNY.cjs.map +7 -0
  75. package/dist/lib/node/markdown-NJDPXIKD.cjs +178 -0
  76. package/dist/lib/node/markdown-NJDPXIKD.cjs.map +7 -0
  77. package/dist/lib/node/meta.json +1 -1
  78. package/dist/lib/node/react-root-HQDBRGD3.cjs +51 -0
  79. package/dist/lib/node/react-root-HQDBRGD3.cjs.map +7 -0
  80. package/dist/lib/node/react-surface-KY5KFKVQ.cjs +122 -0
  81. package/dist/lib/node/react-surface-KY5KFKVQ.cjs.map +7 -0
  82. package/dist/lib/node/{settings-4WLSO726.cjs → settings-H45P5YO2.cjs} +8 -8
  83. package/dist/lib/node/{state-FOHMAVSU.cjs → state-IY5XX3H2.cjs} +8 -8
  84. package/dist/lib/node/{state-FOHMAVSU.cjs.map → state-IY5XX3H2.cjs.map} +3 -3
  85. package/dist/lib/node/{types.cjs → types/index.cjs} +12 -6
  86. package/dist/lib/node/types/index.cjs.map +7 -0
  87. package/dist/lib/node-esm/ChannelContainer-AOXWXM53.mjs +16 -0
  88. package/dist/lib/node-esm/ChannelContainer-AOXWXM53.mjs.map +7 -0
  89. package/dist/lib/node-esm/ChatContainer-UJYPQMLV.mjs +15 -0
  90. package/dist/lib/node-esm/ChatContainer-UJYPQMLV.mjs.map +7 -0
  91. package/dist/lib/node-esm/app-graph-builder-I5VMPLE4.mjs +172 -0
  92. package/dist/lib/node-esm/app-graph-builder-I5VMPLE4.mjs.map +7 -0
  93. package/dist/lib/node-esm/call-manager-B3D3RK3R.mjs +24 -0
  94. package/dist/lib/node-esm/call-manager-B3D3RK3R.mjs.map +7 -0
  95. package/dist/lib/node-esm/chunk-CSO73XLB.mjs +546 -0
  96. package/dist/lib/node-esm/chunk-CSO73XLB.mjs.map +7 -0
  97. package/dist/lib/node-esm/{chunk-42F2DTMM.mjs → chunk-ESQC6SYE.mjs} +4 -4
  98. package/dist/lib/node-esm/chunk-ESQC6SYE.mjs.map +7 -0
  99. package/dist/lib/node-esm/chunk-J323VQ4P.mjs +127 -0
  100. package/dist/lib/node-esm/chunk-J323VQ4P.mjs.map +7 -0
  101. package/dist/lib/node-esm/chunk-JJLYSLLU.mjs +23 -0
  102. package/dist/lib/node-esm/chunk-JJLYSLLU.mjs.map +7 -0
  103. package/dist/lib/node-esm/{chunk-WLY2HMDB.mjs → chunk-K4KAUOKT.mjs} +5 -3
  104. package/dist/lib/node-esm/chunk-K4KAUOKT.mjs.map +7 -0
  105. package/dist/lib/node-esm/{chunk-IZWN4KAY.mjs → chunk-O3V45YJP.mjs} +57 -35
  106. package/dist/lib/node-esm/chunk-O3V45YJP.mjs.map +7 -0
  107. package/dist/lib/node-esm/chunk-PGRP3O4O.mjs +33 -0
  108. package/dist/lib/node-esm/chunk-PGRP3O4O.mjs.map +7 -0
  109. package/dist/lib/node-esm/chunk-POKXRTII.mjs +352 -0
  110. package/dist/lib/node-esm/chunk-POKXRTII.mjs.map +7 -0
  111. package/dist/lib/node-esm/chunk-WBNC7KMA.mjs +1710 -0
  112. package/dist/lib/node-esm/chunk-WBNC7KMA.mjs.map +7 -0
  113. package/dist/lib/node-esm/chunk-X6AUQDTE.mjs +984 -0
  114. package/dist/lib/node-esm/chunk-X6AUQDTE.mjs.map +7 -0
  115. package/dist/lib/node-esm/index.mjs +101 -35
  116. package/dist/lib/node-esm/index.mjs.map +4 -4
  117. package/dist/lib/node-esm/{intent-resolver-X2FNKFSK.mjs → intent-resolver-CU22OPAH.mjs} +95 -62
  118. package/dist/lib/node-esm/intent-resolver-CU22OPAH.mjs.map +7 -0
  119. package/dist/lib/node-esm/markdown-HRGGO7IA.mjs +170 -0
  120. package/dist/lib/node-esm/markdown-HRGGO7IA.mjs.map +7 -0
  121. package/dist/lib/node-esm/meta.json +1 -1
  122. package/dist/lib/node-esm/react-root-MKN5SK3G.mjs +28 -0
  123. package/dist/lib/node-esm/react-root-MKN5SK3G.mjs.map +7 -0
  124. package/dist/lib/node-esm/react-surface-J2C7CVX7.mjs +109 -0
  125. package/dist/lib/node-esm/react-surface-J2C7CVX7.mjs.map +7 -0
  126. package/dist/lib/node-esm/{settings-5UA6FBMW.mjs → settings-IJGUOU3F.mjs} +3 -3
  127. package/dist/lib/node-esm/{state-IRLEO2SB.mjs → state-6AUTNROZ.mjs} +4 -4
  128. package/dist/lib/node-esm/{state-IRLEO2SB.mjs.map → state-6AUTNROZ.mjs.map} +3 -3
  129. package/dist/lib/node-esm/types/index.mjs +17 -0
  130. package/dist/lib/node-esm/types/index.mjs.map +7 -0
  131. package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
  132. package/dist/types/src/calls/call-manager.d.ts +77 -0
  133. package/dist/types/src/calls/call-manager.d.ts.map +1 -0
  134. package/dist/types/src/calls/call-swarm-synchronizer.d.ts +66 -0
  135. package/dist/types/src/calls/call-swarm-synchronizer.d.ts.map +1 -0
  136. package/dist/types/src/calls/index.d.ts +7 -0
  137. package/dist/types/src/calls/index.d.ts.map +1 -0
  138. package/dist/types/src/calls/media-manager.d.ts +60 -0
  139. package/dist/types/src/calls/media-manager.d.ts.map +1 -0
  140. package/dist/types/src/calls/speaking-monitor.d.ts +24 -0
  141. package/dist/types/src/calls/speaking-monitor.d.ts.map +1 -0
  142. package/dist/types/src/calls/types.d.ts +45 -0
  143. package/dist/types/src/calls/types.d.ts.map +1 -0
  144. package/dist/types/src/calls/util/audio.d.ts +6 -0
  145. package/dist/types/src/calls/util/audio.d.ts.map +1 -0
  146. package/dist/types/src/calls/util/calls-service.d.ts +72 -0
  147. package/dist/types/src/calls/util/calls-service.d.ts.map +1 -0
  148. package/dist/types/src/calls/util/history-cache.d.ts +11 -0
  149. package/dist/types/src/calls/util/history-cache.d.ts.map +1 -0
  150. package/dist/types/src/calls/util/index.d.ts +5 -0
  151. package/dist/types/src/calls/util/index.d.ts.map +1 -0
  152. package/dist/types/src/calls/util/media.d.ts +6 -0
  153. package/dist/types/src/calls/util/media.d.ts.map +1 -0
  154. package/dist/types/src/calls/util/stub-media-streams.d.ts +18 -0
  155. package/dist/types/src/calls/util/stub-media-streams.d.ts.map +1 -0
  156. package/dist/types/src/calls/util/task-scheduling.d.ts +17 -0
  157. package/dist/types/src/calls/util/task-scheduling.d.ts.map +1 -0
  158. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  159. package/dist/types/src/capabilities/call-manager.d.ts +5 -0
  160. package/dist/types/src/capabilities/call-manager.d.ts.map +1 -0
  161. package/dist/types/src/capabilities/capabilities.d.ts +13 -1
  162. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  163. package/dist/types/src/capabilities/index.d.ts +5 -0
  164. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  165. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  166. package/dist/types/src/capabilities/markdown.d.ts.map +1 -1
  167. package/dist/types/src/capabilities/react-root.d.ts +7 -0
  168. package/dist/types/src/capabilities/react-root.d.ts.map +1 -0
  169. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  170. package/dist/types/src/components/Call/Call.d.ts +17 -0
  171. package/dist/types/src/components/Call/Call.d.ts.map +1 -0
  172. package/dist/types/src/components/Call/Toolbar.d.ts +16 -0
  173. package/dist/types/src/components/Call/Toolbar.d.ts.map +1 -0
  174. package/dist/types/src/components/Call/index.d.ts +3 -0
  175. package/dist/types/src/components/Call/index.d.ts.map +1 -0
  176. package/dist/types/src/components/CallDebugPanel.d.ts +8 -0
  177. package/dist/types/src/components/CallDebugPanel.d.ts.map +1 -0
  178. package/dist/types/src/components/CallSidebar.d.ts +4 -0
  179. package/dist/types/src/components/CallSidebar.d.ts.map +1 -0
  180. package/dist/types/src/components/ChannelContainer.d.ts +14 -0
  181. package/dist/types/src/components/ChannelContainer.d.ts.map +1 -0
  182. package/dist/types/src/components/ChannelContainer.stories.d.ts +10 -0
  183. package/dist/types/src/components/ChannelContainer.stories.d.ts.map +1 -0
  184. package/dist/types/src/components/ChatContainer.d.ts +9 -7
  185. package/dist/types/src/components/ChatContainer.d.ts.map +1 -1
  186. package/dist/types/src/components/CommentContainer.d.ts +11 -2
  187. package/dist/types/src/components/CommentContainer.d.ts.map +1 -1
  188. package/dist/types/src/components/Comments.stories.d.ts.map +1 -1
  189. package/dist/types/src/components/CommentsContainer.d.ts +5 -9
  190. package/dist/types/src/components/CommentsContainer.d.ts.map +1 -1
  191. package/dist/types/src/components/Lobby/Lobby.d.ts +15 -0
  192. package/dist/types/src/components/Lobby/Lobby.d.ts.map +1 -0
  193. package/dist/types/src/components/Lobby/index.d.ts +2 -0
  194. package/dist/types/src/components/Lobby/index.d.ts.map +1 -0
  195. package/dist/types/src/components/Media/AudioStream.d.ts +6 -0
  196. package/dist/types/src/components/Media/AudioStream.d.ts.map +1 -0
  197. package/dist/types/src/components/Media/VideoObject.d.ts +15 -0
  198. package/dist/types/src/components/Media/VideoObject.d.ts.map +1 -0
  199. package/dist/types/src/components/Media/VideoObject.stories.d.ts +8 -0
  200. package/dist/types/src/components/Media/VideoObject.stories.d.ts.map +1 -0
  201. package/dist/types/src/components/Media/index.d.ts +3 -0
  202. package/dist/types/src/components/Media/index.d.ts.map +1 -0
  203. package/dist/types/src/components/Participant/Participant.d.ts +6 -0
  204. package/dist/types/src/components/Participant/Participant.d.ts.map +1 -0
  205. package/dist/types/src/components/Participant/ParticipantGrid.d.ts +11 -0
  206. package/dist/types/src/components/Participant/ParticipantGrid.d.ts.map +1 -0
  207. package/dist/types/src/components/Participant/index.d.ts +3 -0
  208. package/dist/types/src/components/Participant/index.d.ts.map +1 -0
  209. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.d.ts +12 -0
  210. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.d.ts.map +1 -0
  211. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts +10 -0
  212. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts.map +1 -0
  213. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.d.ts +32 -0
  214. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.d.ts.map +1 -0
  215. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts +23 -0
  216. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts.map +1 -0
  217. package/dist/types/src/components/ResponsiveGrid/ResponsiveGridItem.d.ts +21 -0
  218. package/dist/types/src/components/ResponsiveGrid/ResponsiveGridItem.d.ts.map +1 -0
  219. package/dist/types/src/components/ResponsiveGrid/index.d.ts +4 -0
  220. package/dist/types/src/components/ResponsiveGrid/index.d.ts.map +1 -0
  221. package/dist/types/src/components/ThreadComplementary.d.ts.map +1 -1
  222. package/dist/types/src/components/index.d.ts +5 -1
  223. package/dist/types/src/components/index.d.ts.map +1 -1
  224. package/dist/types/src/components/testing.d.ts +14 -14
  225. package/dist/types/src/components/testing.d.ts.map +1 -1
  226. package/dist/types/src/extensions/threads.d.ts.map +1 -1
  227. package/dist/types/src/hooks/index.d.ts +2 -1
  228. package/dist/types/src/hooks/index.d.ts.map +1 -1
  229. package/dist/types/src/hooks/useDebugMode.d.ts +2 -0
  230. package/dist/types/src/hooks/useDebugMode.d.ts.map +1 -0
  231. package/dist/types/src/index.d.ts +1 -1
  232. package/dist/types/src/index.d.ts.map +1 -1
  233. package/dist/types/src/meta.d.ts.map +1 -1
  234. package/dist/types/src/peers.stories.d.ts +11 -0
  235. package/dist/types/src/peers.stories.d.ts.map +1 -0
  236. package/dist/types/src/testing/index.d.ts +2 -0
  237. package/dist/types/src/testing/index.d.ts.map +1 -0
  238. package/dist/types/src/testing/stories.d.ts +2 -0
  239. package/dist/types/src/testing/stories.d.ts.map +1 -0
  240. package/dist/types/src/translations.d.ts +34 -1
  241. package/dist/types/src/translations.d.ts.map +1 -1
  242. package/dist/types/src/types/index.d.ts +3 -0
  243. package/dist/types/src/types/index.d.ts.map +1 -0
  244. package/dist/types/src/types/schema.d.ts +317 -0
  245. package/dist/types/src/types/schema.d.ts.map +1 -0
  246. package/dist/types/src/types/types.d.ts +1015 -0
  247. package/dist/types/src/types/types.d.ts.map +1 -0
  248. package/dist/types/src/util.d.ts +2 -0
  249. package/dist/types/src/util.d.ts.map +1 -1
  250. package/package.json +54 -41
  251. package/src/ThreadPlugin.tsx +28 -9
  252. package/src/calls/call-manager.ts +242 -0
  253. package/src/calls/call-swarm-synchronizer.ts +350 -0
  254. package/src/calls/index.ts +10 -0
  255. package/src/calls/media-manager.ts +342 -0
  256. package/src/calls/speaking-monitor.ts +85 -0
  257. package/src/calls/types.ts +70 -0
  258. package/src/calls/util/audio.ts +58 -0
  259. package/src/calls/util/calls-service.ts +527 -0
  260. package/src/calls/util/history-cache.ts +27 -0
  261. package/src/calls/util/index.ts +8 -0
  262. package/src/calls/util/media.ts +52 -0
  263. package/src/calls/util/stub-media-streams.ts +73 -0
  264. package/src/calls/util/task-scheduling.ts +92 -0
  265. package/src/capabilities/app-graph-builder.ts +148 -12
  266. package/src/capabilities/call-manager.ts +19 -0
  267. package/src/capabilities/capabilities.ts +15 -1
  268. package/src/capabilities/index.ts +2 -0
  269. package/src/capabilities/intent-resolver.ts +69 -47
  270. package/src/capabilities/markdown.ts +51 -1
  271. package/src/capabilities/react-root.tsx +17 -0
  272. package/src/capabilities/react-surface.tsx +52 -27
  273. package/src/capabilities/state.ts +1 -1
  274. package/src/components/Call/Call.tsx +88 -0
  275. package/src/components/Call/Toolbar.tsx +182 -0
  276. package/src/components/Call/index.ts +6 -0
  277. package/src/components/CallDebugPanel.tsx +115 -0
  278. package/src/components/CallSidebar.tsx +17 -0
  279. package/src/components/ChannelContainer.stories.tsx +58 -0
  280. package/src/components/ChannelContainer.tsx +203 -0
  281. package/src/components/Chat.stories.tsx +6 -6
  282. package/src/components/ChatContainer.tsx +36 -24
  283. package/src/components/CommentContainer.tsx +31 -12
  284. package/src/components/Comments.stories.tsx +13 -11
  285. package/src/components/CommentsContainer.tsx +18 -28
  286. package/src/components/Lobby/Lobby.tsx +119 -0
  287. package/src/components/Lobby/index.ts +5 -0
  288. package/src/components/Media/AudioStream.tsx +67 -0
  289. package/src/components/Media/VideoObject.stories.tsx +52 -0
  290. package/src/components/Media/VideoObject.tsx +58 -0
  291. package/src/components/Media/index.ts +6 -0
  292. package/src/components/Participant/Participant.tsx +57 -0
  293. package/src/components/Participant/ParticipantGrid.tsx +88 -0
  294. package/src/components/Participant/index.ts +6 -0
  295. package/src/components/ResponsiveGrid/ResponsiveContainer.stories.tsx +54 -0
  296. package/src/components/ResponsiveGrid/ResponsiveContainer.tsx +31 -0
  297. package/src/components/ResponsiveGrid/ResponsiveGrid.stories.tsx +156 -0
  298. package/src/components/ResponsiveGrid/ResponsiveGrid.tsx +341 -0
  299. package/src/components/ResponsiveGrid/ResponsiveGridItem.tsx +131 -0
  300. package/src/components/ResponsiveGrid/index.ts +7 -0
  301. package/src/components/ThreadComplementary.tsx +37 -42
  302. package/src/components/index.ts +4 -0
  303. package/src/components/testing.ts +2 -1
  304. package/src/extensions/threads.ts +42 -24
  305. package/src/hooks/index.ts +2 -1
  306. package/src/hooks/useDebugMode.ts +25 -0
  307. package/src/index.ts +1 -1
  308. package/src/meta.ts +4 -3
  309. package/src/peers.stories.tsx +189 -0
  310. package/src/testing/index.ts +5 -0
  311. package/src/testing/stories.ts +50 -0
  312. package/src/translations.ts +44 -3
  313. package/src/types/index.ts +6 -0
  314. package/src/types/schema.ts +29 -0
  315. package/src/{types.ts → types/types.ts} +24 -14
  316. package/src/typings/peermetrics-webrtc-stats.d.ts +30 -0
  317. package/src/util.ts +12 -0
  318. package/dist/lib/browser/ChatContainer-H4XTHM3A.mjs +0 -138
  319. package/dist/lib/browser/ChatContainer-H4XTHM3A.mjs.map +0 -7
  320. package/dist/lib/browser/app-graph-builder-V7UUHGUI.mjs +0 -44
  321. package/dist/lib/browser/app-graph-builder-V7UUHGUI.mjs.map +0 -7
  322. package/dist/lib/browser/chunk-32EIWOAL.mjs.map +0 -7
  323. package/dist/lib/browser/chunk-EP6MRLY7.mjs.map +0 -7
  324. package/dist/lib/browser/chunk-I3JK6CBS.mjs +0 -209
  325. package/dist/lib/browser/chunk-I3JK6CBS.mjs.map +0 -7
  326. package/dist/lib/browser/chunk-OO7PQPV5.mjs +0 -93
  327. package/dist/lib/browser/chunk-OO7PQPV5.mjs.map +0 -7
  328. package/dist/lib/browser/chunk-WBJLUUOK.mjs.map +0 -7
  329. package/dist/lib/browser/chunk-YRGWE35W.mjs +0 -17
  330. package/dist/lib/browser/chunk-YRGWE35W.mjs.map +0 -7
  331. package/dist/lib/browser/intent-resolver-PDOLX5B7.mjs.map +0 -7
  332. package/dist/lib/browser/markdown-XJJVUBDO.mjs +0 -111
  333. package/dist/lib/browser/markdown-XJJVUBDO.mjs.map +0 -7
  334. package/dist/lib/browser/react-surface-7DJZKIOK.mjs +0 -436
  335. package/dist/lib/browser/react-surface-7DJZKIOK.mjs.map +0 -7
  336. package/dist/lib/browser/types.mjs +0 -10
  337. package/dist/lib/node/ChatContainer-TUISUIY7.cjs +0 -163
  338. package/dist/lib/node/ChatContainer-TUISUIY7.cjs.map +0 -7
  339. package/dist/lib/node/app-graph-builder-MMM26FEH.cjs +0 -60
  340. package/dist/lib/node/app-graph-builder-MMM26FEH.cjs.map +0 -7
  341. package/dist/lib/node/chunk-AZ275P4V.cjs.map +0 -7
  342. package/dist/lib/node/chunk-ETDNE4Z6.cjs +0 -234
  343. package/dist/lib/node/chunk-ETDNE4Z6.cjs.map +0 -7
  344. package/dist/lib/node/chunk-GRMB5VRN.cjs +0 -113
  345. package/dist/lib/node/chunk-GRMB5VRN.cjs.map +0 -7
  346. package/dist/lib/node/chunk-NO6WQR36.cjs.map +0 -7
  347. package/dist/lib/node/chunk-NQ5DTPOY.cjs.map +0 -7
  348. package/dist/lib/node/intent-resolver-MNTL32W2.cjs.map +0 -7
  349. package/dist/lib/node/markdown-25NI6Q4Y.cjs +0 -121
  350. package/dist/lib/node/markdown-25NI6Q4Y.cjs.map +0 -7
  351. package/dist/lib/node/react-surface-KGUZJVRL.cjs +0 -438
  352. package/dist/lib/node/react-surface-KGUZJVRL.cjs.map +0 -7
  353. package/dist/lib/node/types.cjs.map +0 -7
  354. package/dist/lib/node-esm/ChatContainer-G7VTTRDN.mjs +0 -139
  355. package/dist/lib/node-esm/ChatContainer-G7VTTRDN.mjs.map +0 -7
  356. package/dist/lib/node-esm/app-graph-builder-QEFJ2KA4.mjs +0 -45
  357. package/dist/lib/node-esm/app-graph-builder-QEFJ2KA4.mjs.map +0 -7
  358. package/dist/lib/node-esm/chunk-42F2DTMM.mjs.map +0 -7
  359. package/dist/lib/node-esm/chunk-5XUQJWUG.mjs +0 -19
  360. package/dist/lib/node-esm/chunk-5XUQJWUG.mjs.map +0 -7
  361. package/dist/lib/node-esm/chunk-A7RLBTTZ.mjs +0 -94
  362. package/dist/lib/node-esm/chunk-A7RLBTTZ.mjs.map +0 -7
  363. package/dist/lib/node-esm/chunk-IZWN4KAY.mjs.map +0 -7
  364. package/dist/lib/node-esm/chunk-V7HLWNAO.mjs +0 -210
  365. package/dist/lib/node-esm/chunk-V7HLWNAO.mjs.map +0 -7
  366. package/dist/lib/node-esm/chunk-WLY2HMDB.mjs.map +0 -7
  367. package/dist/lib/node-esm/intent-resolver-X2FNKFSK.mjs.map +0 -7
  368. package/dist/lib/node-esm/markdown-2ERASVEO.mjs +0 -112
  369. package/dist/lib/node-esm/markdown-2ERASVEO.mjs.map +0 -7
  370. package/dist/lib/node-esm/react-surface-DLD2UJRM.mjs +0 -437
  371. package/dist/lib/node-esm/react-surface-DLD2UJRM.mjs.map +0 -7
  372. package/dist/lib/node-esm/types.mjs +0 -11
  373. package/dist/types/src/components/types.d.ts +0 -28
  374. package/dist/types/src/components/types.d.ts.map +0 -1
  375. package/dist/types/src/events.d.ts +0 -4
  376. package/dist/types/src/events.d.ts.map +0 -1
  377. package/dist/types/src/types.d.ts +0 -276
  378. package/dist/types/src/types.d.ts.map +0 -1
  379. package/src/components/types.ts +0 -32
  380. package/src/events.ts +0 -11
  381. /package/dist/lib/browser/{types.mjs.map → ChannelContainer-XFNGSLHL.mjs.map} +0 -0
  382. /package/dist/lib/{node-esm/types.mjs.map → browser/ChatContainer-JWRI73OG.mjs.map} +0 -0
  383. /package/dist/lib/browser/{settings-K56QXNJ4.mjs.map → settings-KVBQQSO5.mjs.map} +0 -0
  384. /package/dist/lib/node/{settings-4WLSO726.cjs.map → settings-H45P5YO2.cjs.map} +0 -0
  385. /package/dist/lib/node-esm/{settings-5UA6FBMW.mjs.map → settings-IJGUOU3F.mjs.map} +0 -0
@@ -2,30 +2,36 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import React, { useCallback, useEffect, useMemo } from 'react';
6
-
7
- import { createIntent, LayoutAction, useCapability, useCapabilities, useIntentDispatcher } from '@dxos/app-framework';
8
- import { ThreadCapabilities } from '@dxos/plugin-space';
9
- import { type ThreadType } from '@dxos/plugin-space/types';
10
- import { fullyQualifiedId, RefArray } from '@dxos/react-client/echo';
5
+ import React, { useCallback, useMemo } from 'react';
6
+
7
+ import {
8
+ createIntent,
9
+ LayoutAction,
10
+ useCapability,
11
+ useCapabilities,
12
+ useIntentDispatcher,
13
+ Capabilities,
14
+ } from '@dxos/app-framework';
15
+ import { Filter, getTypename, isInstanceOf, Query, RelationSourceId } from '@dxos/echo-schema';
16
+ import { fullyQualifiedId, getSpace, useQuery } from '@dxos/react-client/echo';
11
17
  import { useIdentity } from '@dxos/react-client/halo';
12
18
  import { useTranslation } from '@dxos/react-ui';
13
19
  import { useAttended } from '@dxos/react-ui-attention';
14
20
  import { StackItem } from '@dxos/react-ui-stack';
15
21
  import { Tabs } from '@dxos/react-ui-tabs';
16
- import { isNonNullable } from '@dxos/util';
22
+ import { AnchoredTo } from '@dxos/schema';
17
23
 
18
- import { ThreadCapabilities as LocalThreadCapabilities } from '../capabilities';
24
+ import { ThreadCapabilities } from '../capabilities';
19
25
  import { CommentsContainer } from '../components';
20
26
  import { THREAD_PLUGIN } from '../meta';
21
- import { ThreadAction } from '../types';
27
+ import { ThreadAction, ThreadType } from '../types';
22
28
 
23
29
  export const ThreadComplementary = ({ subject }: { subject: any }) => {
24
30
  const { dispatchPromise: dispatch } = useIntentDispatcher();
25
31
  const identity = useIdentity();
26
32
  const { t } = useTranslation(THREAD_PLUGIN);
27
33
 
28
- const { state, getViewState } = useCapability(LocalThreadCapabilities.MutableState);
34
+ const { state, getViewState } = useCapability(ThreadCapabilities.MutableState);
29
35
  const viewState = getViewState(fullyQualifiedId(subject));
30
36
  const { showResolvedThreads } = viewState;
31
37
  const onChangeViewState = useCallback(
@@ -36,36 +42,24 @@ export const ThreadComplementary = ({ subject }: { subject: any }) => {
36
42
  );
37
43
  const drafts = state.drafts[fullyQualifiedId(subject)];
38
44
 
39
- const threadsIntegrators = useCapabilities(ThreadCapabilities.Thread);
40
- const createSort = useMemo(
41
- () => threadsIntegrators.find((p) => p.predicate(subject))?.createSort,
42
- [threadsIntegrators, subject],
43
- );
44
- const sort = useMemo(() => createSort?.(subject), [createSort, subject]);
45
-
46
- const threadObjects = RefArray.targets(subject.threads ?? []);
45
+ const anchorSorts = useCapabilities(Capabilities.AnchorSort);
46
+ const sort = useMemo(() => anchorSorts.find(({ key }) => key === getTypename(subject))?.sort, [anchorSorts, subject]);
47
47
 
48
- const threads = useMemo(() => {
49
- return threadObjects.concat(drafts ?? []).filter(isNonNullable) as ThreadType[];
50
- }, [JSON.stringify(threadObjects), JSON.stringify(drafts)]);
51
-
52
- const detachedIds = useMemo(() => {
53
- return threads.filter(({ anchor }) => !anchor).map((thread) => fullyQualifiedId(thread));
54
- }, [threads]);
55
-
56
- useEffect(() => {
57
- if (!sort) {
58
- return;
59
- }
60
- threads.sort((a, b) => sort(a?.anchor, b?.anchor));
61
- }, [sort, threads]);
48
+ const space = getSpace(subject);
49
+ const objectsAnchoredTo = useQuery(space, Query.select(Filter.ids(subject.id)).targetOf(AnchoredTo));
50
+ const anchors = objectsAnchoredTo
51
+ .toSorted((a, b) => sort?.(a, b) ?? 0)
52
+ .filter((anchor) => isInstanceOf(ThreadType, anchor[RelationSourceId]))
53
+ .concat(drafts ?? []);
62
54
 
63
55
  const attended = useAttended();
64
56
  const qualifiedSubjectId = fullyQualifiedId(subject);
65
57
 
66
58
  const handleAttend = useCallback(
67
- (thread: ThreadType) => {
59
+ (anchor: AnchoredTo) => {
60
+ const thread = anchor[RelationSourceId] as ThreadType;
68
61
  const threadId = fullyQualifiedId(thread);
62
+
69
63
  if (state.current !== threadId) {
70
64
  state.current = threadId;
71
65
 
@@ -77,7 +71,7 @@ export const ThreadComplementary = ({ subject }: { subject: any }) => {
77
71
  part: 'current',
78
72
  subject: fullyQualifiedId(subject),
79
73
  options: {
80
- cursor: thread.anchor,
74
+ cursor: anchor.anchor,
81
75
  ref: threadId,
82
76
  },
83
77
  }),
@@ -88,36 +82,37 @@ export const ThreadComplementary = ({ subject }: { subject: any }) => {
88
82
  );
89
83
 
90
84
  const handleComment = useCallback(
91
- async (thread: ThreadType, text: string) => {
85
+ async (anchor: AnchoredTo, text: string) => {
92
86
  await dispatch(
93
- createIntent(ThreadAction.AddMessage, { thread, subject, sender: { identityDid: identity?.did }, text }),
87
+ createIntent(ThreadAction.AddMessage, { anchor, subject, sender: { identityDid: identity?.did }, text }),
94
88
  );
95
89
 
90
+ const thread = anchor[RelationSourceId] as ThreadType;
96
91
  state.current = fullyQualifiedId(thread);
97
92
  },
98
93
  [dispatch, identity, subject],
99
94
  );
100
95
 
101
96
  const handleResolve = useCallback(
102
- (thread: ThreadType) => dispatch(createIntent(ThreadAction.ToggleResolved, { thread })),
97
+ (anchor: AnchoredTo) =>
98
+ dispatch(createIntent(ThreadAction.ToggleResolved, { thread: anchor[RelationSourceId] as ThreadType })),
103
99
  [dispatch],
104
100
  );
105
101
 
106
102
  const handleThreadDelete = useCallback(
107
- (thread: ThreadType) => dispatch(createIntent(ThreadAction.Delete, { thread, subject })),
103
+ (anchor: AnchoredTo) => dispatch(createIntent(ThreadAction.Delete, { anchor, subject })),
108
104
  [dispatch, subject],
109
105
  );
110
106
 
111
107
  const handleMessageDelete = useCallback(
112
- (thread: ThreadType, messageId: string) =>
113
- dispatch(createIntent(ThreadAction.DeleteMessage, { thread, subject, messageId })),
108
+ (anchor: AnchoredTo, messageId: string) =>
109
+ dispatch(createIntent(ThreadAction.DeleteMessage, { anchor, subject, messageId })),
114
110
  [dispatch, subject],
115
111
  );
116
112
 
117
113
  const comments = (
118
114
  <CommentsContainer
119
- threads={threads}
120
- detached={detachedIds}
115
+ anchors={anchors}
121
116
  currentId={attended.includes(qualifiedSubjectId) ? state.current : undefined}
122
117
  showResolvedThreads={showResolvedThreads}
123
118
  onAttend={handleAttend}
@@ -4,9 +4,13 @@
4
4
 
5
5
  import { lazy } from 'react';
6
6
 
7
+ export const ChannelContainer = lazy(() => import('./ChannelContainer'));
7
8
  export const ChatContainer = lazy(() => import('./ChatContainer'));
8
9
 
9
10
  // TODO(wittjosiah): Suspense boundary for sidebar?
11
+ export * from './Call';
12
+ export * from './CallDebugPanel';
13
+ export * from './CallSidebar';
10
14
  export * from './CommentContainer';
11
15
  export * from './CommentsContainer';
12
16
  export * from './MessageContainer';
@@ -4,11 +4,12 @@
4
4
 
5
5
  import { IdentityDid } from '@dxos/keys';
6
6
  import { live, makeRef } from '@dxos/live-object';
7
- import { ThreadType } from '@dxos/plugin-space/types';
8
7
  import { faker } from '@dxos/random';
9
8
  import { type Identity } from '@dxos/react-client/halo';
10
9
  import { DataType } from '@dxos/schema';
11
10
 
11
+ import { ThreadType } from '../types';
12
+
12
13
  export const createCommentThread = (identity: Identity) => {
13
14
  return live(ThreadType, {
14
15
  messages: faker.helpers.multiple(
@@ -7,14 +7,13 @@ import { EditorView } from '@codemirror/view';
7
7
  import { computed, effect } from '@preact/signals-core';
8
8
 
9
9
  import { createIntent, type PromiseIntentDispatcher } from '@dxos/app-framework';
10
- import { Ref } from '@dxos/echo-schema';
11
- import { RefArray } from '@dxos/live-object';
10
+ import { Filter, isInstanceOf, Query, RelationSourceId } from '@dxos/echo-schema';
12
11
  import { type DocumentType } from '@dxos/plugin-markdown/types';
13
- import { ThreadType } from '@dxos/plugin-space/types';
14
- import { getSpace, getTextInRange, createDocAccessor, fullyQualifiedId } from '@dxos/react-client/echo';
12
+ import { getSpace, getTextInRange, createDocAccessor, fullyQualifiedId, getSource } from '@dxos/react-client/echo';
15
13
  import { comments, createExternalCommentSync } from '@dxos/react-ui-editor';
14
+ import { AnchoredTo } from '@dxos/schema';
16
15
 
17
- import { ThreadAction, type ThreadState } from '../types';
16
+ import { ThreadAction, ThreadType, type ThreadState } from '../types';
18
17
 
19
18
  // TODO(burdon): Factor out.
20
19
  const getName = (doc: DocumentType, anchor: string): string | undefined => {
@@ -35,21 +34,33 @@ export const threads = (state: ThreadState, doc?: DocumentType, dispatch?: Promi
35
34
  return [comments()];
36
35
  }
37
36
 
38
- // TODO(Zan): When we have the deepsignal specific equivalent of this we should use that instead.
39
- const threads = computed(() =>
40
- [...RefArray.targets(doc.threads), ...(state.drafts[fullyQualifiedId(doc)] ?? [])].filter(
41
- (thread) => !(thread?.status === 'resolved'),
42
- ),
37
+ const query = space.db.query(Query.select(Filter.ids(doc.id)).targetOf(AnchoredTo));
38
+ const unsubscribe = query.subscribe();
39
+
40
+ const anchors = computed(() =>
41
+ query.objects
42
+ .filter((anchor) => {
43
+ const thread = anchor[RelationSourceId];
44
+ return isInstanceOf(ThreadType, thread) && thread.status !== 'resolved';
45
+ })
46
+ .concat(state.drafts[fullyQualifiedId(doc)] ?? []),
43
47
  );
44
48
 
45
49
  return [
50
+ EditorView.domEventHandlers({
51
+ destroy: () => {
52
+ unsubscribe();
53
+ },
54
+ }),
55
+
46
56
  EditorView.updateListener.of((update) => {
47
57
  if (update.docChanged) {
48
- RefArray.targets(doc.threads).forEach((thread) => {
49
- if (thread.anchor) {
58
+ anchors.value.forEach((anchor) => {
59
+ if (anchor.anchor) {
50
60
  // Only update if the name has changed, otherwise this will cause an infinite loop.
51
61
  // Skip if the name is empty; this means comment text was deleted, but thread name should remain.
52
- const name = getName(doc, thread.anchor);
62
+ const name = getName(doc, anchor.anchor);
63
+ const thread = anchor[RelationSourceId] as ThreadType;
53
64
  if (name && name !== thread.name) {
54
65
  thread.name = name;
55
66
  }
@@ -62,16 +73,16 @@ export const threads = (state: ThreadState, doc?: DocumentType, dispatch?: Promi
62
73
  fullyQualifiedId(doc),
63
74
  (sink) => effect(() => sink()),
64
75
  () =>
65
- threads.value
66
- .filter((thread) => thread?.anchor)
67
- .map((thread) => ({ id: fullyQualifiedId(thread), cursor: thread.anchor! })),
76
+ anchors.value
77
+ .filter((anchor) => anchor.anchor)
78
+ .map((anchor) => ({ id: fullyQualifiedId(anchor[RelationSourceId]), cursor: anchor.anchor })),
68
79
  ),
69
80
 
70
81
  comments({
71
82
  id: fullyQualifiedId(doc),
72
83
  onCreate: ({ cursor }) => {
73
84
  const name = getName(doc, cursor);
74
- void dispatch(createIntent(ThreadAction.Create, { cursor, name, subject: doc }));
85
+ void dispatch(createIntent(ThreadAction.Create, { anchor: cursor, name, subject: doc }));
75
86
  },
76
87
  onDelete: ({ id }) => {
77
88
  const draft = state.drafts[fullyQualifiedId(doc)];
@@ -82,19 +93,26 @@ export const threads = (state: ThreadState, doc?: DocumentType, dispatch?: Promi
82
93
  }
83
94
  }
84
95
 
85
- const thread = doc.threads.find(Ref.hasObjectId(id))?.target;
96
+ const thread = query.objects.find((object) => getSource(object).id === id);
86
97
  if (thread) {
87
98
  thread.anchor = undefined;
88
99
  }
89
100
  },
90
101
  onUpdate: ({ id, cursor }) => {
91
- const thread =
92
- state.drafts[fullyQualifiedId(doc)]?.find((thread) => fullyQualifiedId(thread) === id) ??
93
- doc.threads.find(Ref.hasObjectId(id))?.target;
102
+ const draft = state.drafts[fullyQualifiedId(doc)]?.find((thread) => fullyQualifiedId(thread) === id);
103
+ if (draft) {
104
+ const thread = draft[RelationSourceId] as ThreadType;
105
+ thread.name = getName(doc, cursor);
106
+ draft.anchor = cursor;
107
+ }
94
108
 
95
- if (thread instanceof ThreadType && thread.anchor) {
96
- thread.name = getName(doc, thread.anchor);
97
- thread.anchor = cursor;
109
+ const relation = query.objects.find((object) => getSource(object).id === id);
110
+ if (relation) {
111
+ const thread = getSource(relation);
112
+ if (isInstanceOf(ThreadType, thread)) {
113
+ thread.name = getName(doc, cursor);
114
+ relation.anchor = cursor;
115
+ }
98
116
  }
99
117
  },
100
118
  onSelect: ({ selection }) => {
@@ -2,5 +2,6 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- export * from './useStatus';
6
5
  export * from './analytics';
6
+ export * from './useDebugMode';
7
+ export * from './useStatus';
@@ -0,0 +1,25 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { useState, useEffect } from 'react';
6
+
7
+ // TODO(burdon): Standardize across plugins/composer.
8
+ export const useDebugMode = () => {
9
+ const [enabled, setEnabled] = useState(false);
10
+ useEffect(() => {
11
+ const handler = (ev: KeyboardEvent) => {
12
+ if (ev.key.toLowerCase() === 'd' && ev.ctrlKey) {
13
+ ev.preventDefault();
14
+ setEnabled(!enabled);
15
+ }
16
+ };
17
+
18
+ document.addEventListener('keypress', handler);
19
+ return () => {
20
+ document.removeEventListener('keypress', handler);
21
+ };
22
+ }, [enabled]);
23
+
24
+ return enabled;
25
+ };
package/src/index.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  export { ThreadCapabilities } from './capabilities';
6
- export * from './events';
6
+ export * from './calls';
7
7
  export * from './hooks';
8
8
  export * from './meta';
9
9
 
package/src/meta.ts CHANGED
@@ -7,10 +7,11 @@ import { type PluginMeta } from '@dxos/app-framework';
7
7
  export const THREAD_PLUGIN = 'dxos.org/plugin/thread';
8
8
  export const THREAD_ITEM = `${THREAD_PLUGIN}/item`;
9
9
 
10
+ // TODO(wittjosiah): Needs screenshots.
10
11
  export const meta: PluginMeta = {
11
12
  id: THREAD_PLUGIN,
12
- name: 'Threads',
13
- description: 'Add comment threads to objects.',
14
- icon: 'ph--chat--regular',
13
+ name: 'Chat',
14
+ description: 'Chat via text, voice, and video in channels or create comment threads on objects.',
15
+ icon: 'ph--video-conference--regular',
15
16
  source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-thread',
16
17
  };
@@ -0,0 +1,189 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import { type StoryObj, type Meta } from '@storybook/react';
8
+ import React, { useEffect, useMemo, useRef, useState } from 'react';
9
+
10
+ import { scheduleTask, sleep } from '@dxos/async';
11
+ import { Context } from '@dxos/context';
12
+ import { invariant } from '@dxos/invariant';
13
+ import { log } from '@dxos/log';
14
+ import { Config, useConfig } from '@dxos/react-client';
15
+ import { withClientProvider } from '@dxos/react-client/testing';
16
+ import { Button } from '@dxos/react-ui';
17
+ import { Json } from '@dxos/react-ui-syntax-highlighter';
18
+ import { withLayout, withTheme } from '@dxos/storybook-utils';
19
+
20
+ import { type TrackObject, CallsServicePeer, CALLS_URL } from './calls';
21
+ // @ts-ignore
22
+ import video from '../testing/video.mp4';
23
+
24
+ const useVideoStreamTrack = (videoElement: HTMLVideoElement | null) => {
25
+ // Get video stream track.
26
+ const [videoStreamTrack, setVideoStreamTrack] = useState<MediaStreamTrack | undefined>(undefined);
27
+ const hadRun = useRef(false);
28
+ useEffect(() => {
29
+ // This is done to capture only one video stream.
30
+ if (!videoElement || hadRun.current || !video) {
31
+ return;
32
+ }
33
+ hadRun.current = true;
34
+
35
+ videoElement.src = video;
36
+ videoElement.addEventListener('playing', () => {
37
+ const stream = (videoElement as any).captureStream();
38
+ log.info('captured stream', { stream });
39
+ stream.onaddtrack = (event: MediaStreamTrackEvent) => {
40
+ if (event.track.kind === 'video') {
41
+ log.info('video stream track state', { state: event.track.readyState });
42
+ setVideoStreamTrack(event.track);
43
+ }
44
+ };
45
+ });
46
+ }, [videoElement]);
47
+
48
+ return videoStreamTrack;
49
+ };
50
+
51
+ const DefaultStory = ({ videoSrc }: { videoSrc: string }) => {
52
+ const config = useConfig();
53
+ const callsConfig = {
54
+ iceServers: config.get('runtime.services.ice'),
55
+ apiBase: `${CALLS_URL}/api/calls`,
56
+ };
57
+ const peerPush = useMemo(() => new CallsServicePeer(callsConfig), []);
58
+ const peerPull = useMemo(() => new CallsServicePeer(callsConfig), []);
59
+ const pushVideoElement = useRef<HTMLVideoElement>(null);
60
+ const pullVideoElement = useRef<HTMLVideoElement>(null);
61
+ const [metrics, setMetrics] = useState<Record<string, any>>({});
62
+ // Get video stream track.
63
+ const videoStreamTrack = useVideoStreamTrack(pushVideoElement.current);
64
+ const pullCtx = useRef<Context | undefined>(undefined);
65
+ const trackInfo = useRef<TrackObject | undefined>(undefined);
66
+ const hadRun = useRef(false);
67
+
68
+ // Push/pull video stream track to cloudflare.
69
+ useEffect(() => {
70
+ if (hadRun.current || !videoStreamTrack || !peerPush || !peerPull) {
71
+ return;
72
+ }
73
+ hadRun.current = true;
74
+ const ctx = new Context();
75
+ scheduleTask(ctx, async () => {
76
+ log.info('starting push/pull', { videoStreamTrack });
77
+ await peerPush.open();
78
+ await peerPull.open();
79
+ ctx.onDispose(() => {
80
+ void peerPush.close();
81
+ void peerPull.close();
82
+ });
83
+
84
+ // Push track to cloudflare.
85
+ performance.mark('push:begin');
86
+ const pushedTrack = await peerPush.pushTrack({ track: videoStreamTrack });
87
+ trackInfo.current = pushedTrack;
88
+ performance.mark('push:end');
89
+ const pushTime = performance.measure('push', 'push:begin', 'push:end').duration;
90
+ log.info('successfully pushed track', { pushTime, pushedTrack });
91
+ setMetrics((prev) => ({ ...prev, 'time to push track [ms]': Math.round(pushTime) }));
92
+
93
+ // Wait for cloudflare to process the track.
94
+ await sleep(500);
95
+
96
+ // Pull track from cloudflare.
97
+ performance.mark('pullTrack:begin');
98
+ pullCtx.current = new Context();
99
+ const pulledTrack = await peerPull.pullTrack({
100
+ trackData: { ...pushedTrack, mid: undefined },
101
+ ctx: pullCtx.current,
102
+ });
103
+ performance.mark('pullTrack:end');
104
+ const pullTime = performance.measure('pullTrack', 'pullTrack:begin', 'pullTrack:end').duration;
105
+ setMetrics((prev) => ({ ...prev, 'time to pull track [ms]': Math.round(pullTime) }));
106
+ log.info('successfully pulled track', { pullTime, pulledTrack });
107
+
108
+ invariant(pulledTrack);
109
+ invariant(pullVideoElement.current);
110
+ performance.mark('playVideo:begin');
111
+ pullVideoElement.current.srcObject = new MediaStream([pulledTrack]);
112
+ await pullVideoElement.current.play();
113
+ performance.mark('playVideo:end');
114
+ const playTime = performance.measure('playVideo', 'playVideo:begin', 'playVideo:end').duration;
115
+ setMetrics((prev) => ({ ...prev, 'time to play pulled video [ms]': Math.round(playTime) }));
116
+ });
117
+
118
+ return () => {
119
+ void ctx.dispose();
120
+ };
121
+ }, [videoStreamTrack, peerPush, peerPull]);
122
+
123
+ const handleRePullVideo = async () => {
124
+ performance.mark('rePullVideo:begin');
125
+ invariant(pullVideoElement.current);
126
+ invariant(pullVideoElement.current.srcObject instanceof MediaStream);
127
+ const pulledTrack = pullVideoElement.current.srcObject.getTracks()[0];
128
+ invariant(pulledTrack);
129
+ pullVideoElement.current.srcObject.removeTrack(pulledTrack);
130
+ await pullCtx.current!.dispose();
131
+ pulledTrack.stop();
132
+ pullCtx.current = new Context();
133
+ const newPulledTrack = await peerPull.pullTrack({
134
+ trackData: { ...trackInfo.current!, mid: undefined },
135
+ ctx: pullCtx.current,
136
+ });
137
+ invariant(newPulledTrack);
138
+ pullVideoElement.current.srcObject.addTrack(newPulledTrack);
139
+ performance.mark('rePullVideo:end');
140
+ const rePullTime = performance.measure('rePullVideo', 'rePullVideo:begin', 'rePullVideo:end').duration;
141
+ setMetrics((prev) => ({ ...prev, 'time to re-pull video [ms]': Math.round(rePullTime) }));
142
+ };
143
+
144
+ return (
145
+ <div className='grid grid-cols-3 gap-4 items-center'>
146
+ <video ref={pushVideoElement} muted autoPlay src={video} loop />
147
+ <Json data={metrics} />
148
+ <div className='flex flex-col gap-4'>
149
+ <video ref={pullVideoElement} muted />
150
+ <Button
151
+ disabled={
152
+ !(
153
+ pullVideoElement?.current?.srcObject instanceof MediaStream &&
154
+ pullVideoElement.current.srcObject.getTracks()[0]
155
+ )
156
+ }
157
+ onClick={handleRePullVideo}
158
+ >
159
+ Re-pull video
160
+ </Button>
161
+ </div>
162
+ </div>
163
+ );
164
+ };
165
+
166
+ const meta: Meta<typeof DefaultStory> = {
167
+ title: 'plugins/plugin-thread/peers',
168
+ render: DefaultStory,
169
+ decorators: [
170
+ withClientProvider({
171
+ config: new Config({ runtime: { services: { iceProviders: [{ urls: 'https://edge.dxos.workers.dev/ice' }] } } }),
172
+ }),
173
+ withTheme,
174
+ withLayout(),
175
+ ],
176
+ parameters: {
177
+ layout: 'centered',
178
+ },
179
+ };
180
+
181
+ export default meta;
182
+
183
+ type Story = StoryObj<typeof DefaultStory>;
184
+
185
+ export const Default: Story = {
186
+ args: {
187
+ videoSrc: video,
188
+ },
189
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './stories';
@@ -0,0 +1,50 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { IntentPlugin, SettingsPlugin } from '@dxos/app-framework';
6
+ import { live } from '@dxos/live-object';
7
+ import { ClientPlugin } from '@dxos/plugin-client';
8
+ import { GraphPlugin } from '@dxos/plugin-graph';
9
+ import { SpacePlugin } from '@dxos/plugin-space';
10
+ import { ThemePlugin } from '@dxos/plugin-theme';
11
+ import { Config } from '@dxos/react-client';
12
+ import { Ref } from '@dxos/react-client/echo';
13
+ import { defaultTx } from '@dxos/react-ui-theme';
14
+
15
+ import { ThreadPlugin } from '../ThreadPlugin';
16
+ import { ChannelType, ThreadType } from '../types';
17
+
18
+ export const createThreadPlugins = async () => [
19
+ ThemePlugin({ tx: defaultTx }),
20
+ ClientPlugin({
21
+ onClientInitialized: async (_, client) => {
22
+ await client.halo.createIdentity({ displayName: 'Test User' });
23
+ },
24
+ onSpacesReady: async (_, client) => {
25
+ await client.spaces.default.waitUntilReady();
26
+ const thread = live(ThreadType, { messages: [] });
27
+ client.spaces.default.db.add(live(ChannelType, { defaultThread: Ref.make(thread), threads: [] }));
28
+ },
29
+ config: new Config({
30
+ runtime: {
31
+ client: { edgeFeatures: { signaling: true } },
32
+ services: {
33
+ edge: {
34
+ url: 'https://edge.dxos.workers.dev/',
35
+ },
36
+ iceProviders: [
37
+ {
38
+ urls: 'https://edge.dxos.workers.dev/ice',
39
+ },
40
+ ],
41
+ },
42
+ },
43
+ }),
44
+ }),
45
+ SpacePlugin(),
46
+ IntentPlugin(),
47
+ SettingsPlugin(),
48
+ GraphPlugin(),
49
+ ThreadPlugin(),
50
+ ];
@@ -2,9 +2,8 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { ChannelType } from '@dxos/plugin-space/types';
6
-
7
5
  import { THREAD_PLUGIN } from './meta';
6
+ import { ChannelType } from './types';
8
7
 
9
8
  export default [
10
9
  {
@@ -14,7 +13,7 @@ export default [
14
13
  'object name placeholder': 'New channel',
15
14
  },
16
15
  [THREAD_PLUGIN]: {
17
- 'plugin name': 'Threads',
16
+ 'plugin name': 'Chat',
18
17
  'channel title label': 'Title',
19
18
  'message placeholder': 'Reply…',
20
19
  'activity message': 'Processing…',
@@ -41,6 +40,48 @@ export default [
41
40
  'comments label': 'Comments',
42
41
  'show all label': 'All comments',
43
42
  'show unresolved label': 'Unresolved only',
43
+
44
+ 'channel companion label': 'Channel',
45
+ 'call panel label': 'Active Call',
46
+
47
+ 'display name label': 'Display name',
48
+ 'display name description': 'Set your display name before joining a meeting.',
49
+ 'display name input placeholder': 'Enter your name',
50
+ 'set display name label': 'Continue',
51
+
52
+ 'call tab label': 'Call',
53
+ 'meeting status title': 'Meeting',
54
+ 'share meeting link label': 'Share meeting',
55
+ 'show webrtc stats title': 'Detailed WebRTC Stats',
56
+
57
+ 'meeting summary label': 'Summary',
58
+ 'summarize label': 'Summarize',
59
+ 'summarizing label': 'Creating summary...',
60
+ 'create summary message': 'A summary doesn’t exist for this meeting yet. Create one now?',
61
+
62
+ 'join call': 'Join',
63
+ 'leave call': 'Leave',
64
+
65
+ 'lobby participants_zero': 'No participants',
66
+ 'lobby participants_one': '1 participant',
67
+ 'lobby participants_other': '{{count}} participants',
68
+
69
+ 'icon pin': 'Pin video',
70
+ 'icon unpin': 'Unpin video',
71
+ 'icon wave': 'Waving',
72
+ 'icon muted': 'Muted',
73
+ 'icon speaking': 'Speaking',
74
+
75
+ 'mic on': 'Unmute',
76
+ 'mic off': 'Mute',
77
+ 'camera on': 'Turn camera on',
78
+ 'camera off': 'Turn camera off',
79
+ 'camera off label': 'Camera off',
80
+
81
+ 'raise hand': 'Raise hand',
82
+ 'lower hand': 'Lower hand',
83
+ 'screenshare on': 'Share screen',
84
+ 'screenshare off': 'Stop streaming',
44
85
  },
45
86
  },
46
87
  },