@dxos/plugin-thread 0.8.2-staging.7ac8446 → 0.8.2

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 (407) hide show
  1. package/dist/lib/browser/ChannelContainer-LGYSQMC7.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-APQAZWHT.mjs +23 -0
  6. package/dist/lib/browser/call-manager-APQAZWHT.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-4H4A264L.mjs +1708 -0
  8. package/dist/lib/browser/chunk-4H4A264L.mjs.map +7 -0
  9. package/dist/lib/browser/{chunk-QDJ3Y6WF.mjs → chunk-5P5BH5GE.mjs} +57 -35
  10. package/dist/lib/browser/chunk-5P5BH5GE.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-5PGLGDIP.mjs +983 -0
  12. package/dist/lib/browser/chunk-5PGLGDIP.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-CF2MXRCH.mjs +21 -0
  14. package/dist/lib/browser/chunk-CF2MXRCH.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-G3TS64FP.mjs +351 -0
  16. package/dist/lib/browser/chunk-G3TS64FP.mjs.map +7 -0
  17. package/dist/lib/browser/{chunk-WBJLUUOK.mjs → chunk-IIUTBDVB.mjs} +4 -4
  18. package/dist/lib/browser/chunk-IIUTBDVB.mjs.map +7 -0
  19. package/dist/lib/browser/chunk-JKQUJOTX.mjs +31 -0
  20. package/dist/lib/browser/chunk-JKQUJOTX.mjs.map +7 -0
  21. package/dist/lib/browser/chunk-KMVGJG23.mjs +545 -0
  22. package/dist/lib/browser/chunk-KMVGJG23.mjs.map +7 -0
  23. package/dist/lib/browser/{chunk-EP6MRLY7.mjs → chunk-R5MDLUPC.mjs} +5 -3
  24. package/dist/lib/browser/chunk-R5MDLUPC.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 +107 -41
  28. package/dist/lib/browser/index.mjs.map +4 -4
  29. package/dist/lib/browser/{intent-resolver-QAY4FLLM.mjs → intent-resolver-YUYZCTLF.mjs} +102 -74
  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-EECCWHCW.mjs +27 -0
  35. package/dist/lib/browser/react-root-EECCWHCW.mjs.map +7 -0
  36. package/dist/lib/browser/react-surface-5QLZAFDL.mjs +108 -0
  37. package/dist/lib/browser/react-surface-5QLZAFDL.mjs.map +7 -0
  38. package/dist/lib/browser/{settings-4FEC7EAX.mjs → settings-KVBQQSO5.mjs} +5 -5
  39. package/dist/lib/browser/settings-KVBQQSO5.mjs.map +7 -0
  40. package/dist/lib/browser/{state-PNMSLKAH.mjs → state-RKL5MSDP.mjs} +7 -7
  41. package/dist/lib/browser/state-RKL5MSDP.mjs.map +7 -0
  42. package/dist/lib/browser/types/index.mjs +16 -0
  43. package/dist/lib/browser/types/index.mjs.map +7 -0
  44. package/dist/lib/node/ChannelContainer-5EKNEH56.cjs +36 -0
  45. package/dist/lib/node/ChannelContainer-5EKNEH56.cjs.map +7 -0
  46. package/dist/lib/node/ChatContainer-EE3FPSYO.cjs +35 -0
  47. package/dist/lib/node/ChatContainer-EE3FPSYO.cjs.map +7 -0
  48. package/dist/lib/node/app-graph-builder-IRE3GYKE.cjs +179 -0
  49. package/dist/lib/node/app-graph-builder-IRE3GYKE.cjs.map +7 -0
  50. package/dist/lib/node/call-manager-HV2XJW5O.cjs +37 -0
  51. package/dist/lib/node/call-manager-HV2XJW5O.cjs.map +7 -0
  52. package/dist/lib/node/chunk-44I33JDT.cjs +1731 -0
  53. package/dist/lib/node/chunk-44I33JDT.cjs.map +7 -0
  54. package/dist/lib/node/chunk-4B3PPXA6.cjs +371 -0
  55. package/dist/lib/node/chunk-4B3PPXA6.cjs.map +7 -0
  56. package/dist/lib/node/{chunk-NQ5DTPOY.cjs → chunk-4YSNVPWU.cjs} +10 -8
  57. package/dist/lib/node/chunk-4YSNVPWU.cjs.map +7 -0
  58. package/dist/lib/node/chunk-6B3M6XRE.cjs +984 -0
  59. package/dist/lib/node/chunk-6B3M6XRE.cjs.map +7 -0
  60. package/dist/lib/node/{chunk-AKINTFBH.cjs → chunk-FUXJAVFZ.cjs} +50 -29
  61. package/dist/lib/node/chunk-FUXJAVFZ.cjs.map +7 -0
  62. package/dist/lib/node/{chunk-ONLWOUYZ.cjs → chunk-HLMCEE5K.cjs} +7 -7
  63. package/dist/lib/node/{chunk-ONLWOUYZ.cjs.map → chunk-HLMCEE5K.cjs.map} +2 -2
  64. package/dist/lib/node/chunk-JLHENFGK.cjs +549 -0
  65. package/dist/lib/node/chunk-JLHENFGK.cjs.map +7 -0
  66. package/dist/lib/node/chunk-LR5NENBE.cjs +54 -0
  67. package/dist/lib/node/chunk-LR5NENBE.cjs.map +7 -0
  68. package/dist/lib/node/chunk-TKHJVC2C.cjs +147 -0
  69. package/dist/lib/node/chunk-TKHJVC2C.cjs.map +7 -0
  70. package/dist/lib/node/{chunk-S2A6BXEA.cjs → chunk-U7NOIXN6.cjs} +16 -10
  71. package/dist/lib/node/chunk-U7NOIXN6.cjs.map +7 -0
  72. package/dist/lib/node/index.cjs +142 -80
  73. package/dist/lib/node/index.cjs.map +4 -4
  74. package/dist/lib/node/{intent-resolver-S6FE5OR7.cjs → intent-resolver-MZ3HADNY.cjs} +108 -82
  75. package/dist/lib/node/intent-resolver-MZ3HADNY.cjs.map +7 -0
  76. package/dist/lib/node/markdown-NJDPXIKD.cjs +178 -0
  77. package/dist/lib/node/markdown-NJDPXIKD.cjs.map +7 -0
  78. package/dist/lib/node/meta.json +1 -1
  79. package/dist/lib/node/react-root-IAYQ2DBO.cjs +51 -0
  80. package/dist/lib/node/react-root-IAYQ2DBO.cjs.map +7 -0
  81. package/dist/lib/node/react-surface-AVC5VVIS.cjs +122 -0
  82. package/dist/lib/node/react-surface-AVC5VVIS.cjs.map +7 -0
  83. package/dist/lib/node/{settings-IXCPE55J.cjs → settings-H45P5YO2.cjs} +9 -9
  84. package/dist/lib/node/settings-H45P5YO2.cjs.map +7 -0
  85. package/dist/lib/node/{state-AT73KPGZ.cjs → state-IY5XX3H2.cjs} +10 -10
  86. package/dist/lib/node/state-IY5XX3H2.cjs.map +7 -0
  87. package/dist/lib/node/{types.cjs → types/index.cjs} +12 -6
  88. package/dist/lib/node/types/index.cjs.map +7 -0
  89. package/dist/lib/node-esm/ChannelContainer-KFS2RWWW.mjs +16 -0
  90. package/dist/lib/node-esm/ChannelContainer-KFS2RWWW.mjs.map +7 -0
  91. package/dist/lib/node-esm/ChatContainer-UJYPQMLV.mjs +15 -0
  92. package/dist/lib/node-esm/ChatContainer-UJYPQMLV.mjs.map +7 -0
  93. package/dist/lib/node-esm/app-graph-builder-I5VMPLE4.mjs +172 -0
  94. package/dist/lib/node-esm/app-graph-builder-I5VMPLE4.mjs.map +7 -0
  95. package/dist/lib/node-esm/call-manager-UUYXLF4T.mjs +24 -0
  96. package/dist/lib/node-esm/call-manager-UUYXLF4T.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-WLY2HMDB.mjs → chunk-K4KAUOKT.mjs} +5 -3
  102. package/dist/lib/node-esm/chunk-K4KAUOKT.mjs.map +7 -0
  103. package/dist/lib/node-esm/chunk-MNJ3V4XM.mjs +546 -0
  104. package/dist/lib/node-esm/chunk-MNJ3V4XM.mjs.map +7 -0
  105. package/dist/lib/node-esm/{chunk-J56FORYF.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-ODUB4GAB.mjs +23 -0
  108. package/dist/lib/node-esm/chunk-ODUB4GAB.mjs.map +7 -0
  109. package/dist/lib/node-esm/chunk-PGRP3O4O.mjs +33 -0
  110. package/dist/lib/node-esm/chunk-PGRP3O4O.mjs.map +7 -0
  111. package/dist/lib/node-esm/chunk-POKXRTII.mjs +352 -0
  112. package/dist/lib/node-esm/chunk-POKXRTII.mjs.map +7 -0
  113. package/dist/lib/node-esm/chunk-WXNPD542.mjs +1710 -0
  114. package/dist/lib/node-esm/chunk-WXNPD542.mjs.map +7 -0
  115. package/dist/lib/node-esm/chunk-X6AUQDTE.mjs +984 -0
  116. package/dist/lib/node-esm/chunk-X6AUQDTE.mjs.map +7 -0
  117. package/dist/lib/node-esm/index.mjs +107 -41
  118. package/dist/lib/node-esm/index.mjs.map +4 -4
  119. package/dist/lib/node-esm/{intent-resolver-OURFRSSF.mjs → intent-resolver-CU22OPAH.mjs} +102 -74
  120. package/dist/lib/node-esm/intent-resolver-CU22OPAH.mjs.map +7 -0
  121. package/dist/lib/node-esm/markdown-HRGGO7IA.mjs +170 -0
  122. package/dist/lib/node-esm/markdown-HRGGO7IA.mjs.map +7 -0
  123. package/dist/lib/node-esm/meta.json +1 -1
  124. package/dist/lib/node-esm/react-root-NQMUEI6Z.mjs +28 -0
  125. package/dist/lib/node-esm/react-root-NQMUEI6Z.mjs.map +7 -0
  126. package/dist/lib/node-esm/react-surface-Z4X5VLMY.mjs +109 -0
  127. package/dist/lib/node-esm/react-surface-Z4X5VLMY.mjs.map +7 -0
  128. package/dist/lib/node-esm/{settings-ZUJQ4LWI.mjs → settings-IJGUOU3F.mjs} +5 -5
  129. package/dist/lib/node-esm/settings-IJGUOU3F.mjs.map +7 -0
  130. package/dist/lib/node-esm/{state-SSDX5O67.mjs → state-6AUTNROZ.mjs} +7 -7
  131. package/dist/lib/node-esm/state-6AUTNROZ.mjs.map +7 -0
  132. package/dist/lib/node-esm/types/index.mjs +17 -0
  133. package/dist/lib/node-esm/types/index.mjs.map +7 -0
  134. package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
  135. package/dist/types/src/calls/call-manager.d.ts +77 -0
  136. package/dist/types/src/calls/call-manager.d.ts.map +1 -0
  137. package/dist/types/src/calls/call-swarm-synchronizer.d.ts +66 -0
  138. package/dist/types/src/calls/call-swarm-synchronizer.d.ts.map +1 -0
  139. package/dist/types/src/calls/index.d.ts +7 -0
  140. package/dist/types/src/calls/index.d.ts.map +1 -0
  141. package/dist/types/src/calls/media-manager.d.ts +60 -0
  142. package/dist/types/src/calls/media-manager.d.ts.map +1 -0
  143. package/dist/types/src/calls/speaking-monitor.d.ts +24 -0
  144. package/dist/types/src/calls/speaking-monitor.d.ts.map +1 -0
  145. package/dist/types/src/calls/types.d.ts +45 -0
  146. package/dist/types/src/calls/types.d.ts.map +1 -0
  147. package/dist/types/src/calls/util/audio.d.ts +6 -0
  148. package/dist/types/src/calls/util/audio.d.ts.map +1 -0
  149. package/dist/types/src/calls/util/calls-service.d.ts +72 -0
  150. package/dist/types/src/calls/util/calls-service.d.ts.map +1 -0
  151. package/dist/types/src/calls/util/history-cache.d.ts +11 -0
  152. package/dist/types/src/calls/util/history-cache.d.ts.map +1 -0
  153. package/dist/types/src/calls/util/index.d.ts +5 -0
  154. package/dist/types/src/calls/util/index.d.ts.map +1 -0
  155. package/dist/types/src/calls/util/media.d.ts +6 -0
  156. package/dist/types/src/calls/util/media.d.ts.map +1 -0
  157. package/dist/types/src/calls/util/stub-media-streams.d.ts +18 -0
  158. package/dist/types/src/calls/util/stub-media-streams.d.ts.map +1 -0
  159. package/dist/types/src/calls/util/task-scheduling.d.ts +17 -0
  160. package/dist/types/src/calls/util/task-scheduling.d.ts.map +1 -0
  161. package/dist/types/src/capabilities/app-graph-builder.d.ts +2 -179
  162. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  163. package/dist/types/src/capabilities/call-manager.d.ts +5 -0
  164. package/dist/types/src/capabilities/call-manager.d.ts.map +1 -0
  165. package/dist/types/src/capabilities/capabilities.d.ts +13 -1
  166. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  167. package/dist/types/src/capabilities/index.d.ts +8 -179
  168. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  169. package/dist/types/src/capabilities/intent-resolver.d.ts +2 -2
  170. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  171. package/dist/types/src/capabilities/markdown.d.ts +2 -2
  172. package/dist/types/src/capabilities/markdown.d.ts.map +1 -1
  173. package/dist/types/src/capabilities/react-root.d.ts +7 -0
  174. package/dist/types/src/capabilities/react-root.d.ts.map +1 -0
  175. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  176. package/dist/types/src/components/Call/Call.d.ts +17 -0
  177. package/dist/types/src/components/Call/Call.d.ts.map +1 -0
  178. package/dist/types/src/components/Call/Toolbar.d.ts +16 -0
  179. package/dist/types/src/components/Call/Toolbar.d.ts.map +1 -0
  180. package/dist/types/src/components/Call/index.d.ts +3 -0
  181. package/dist/types/src/components/Call/index.d.ts.map +1 -0
  182. package/dist/types/src/components/CallDebugPanel.d.ts +8 -0
  183. package/dist/types/src/components/CallDebugPanel.d.ts.map +1 -0
  184. package/dist/types/src/components/CallSidebar.d.ts +4 -0
  185. package/dist/types/src/components/CallSidebar.d.ts.map +1 -0
  186. package/dist/types/src/components/ChannelContainer.d.ts +14 -0
  187. package/dist/types/src/components/ChannelContainer.d.ts.map +1 -0
  188. package/dist/types/src/components/ChannelContainer.stories.d.ts +10 -0
  189. package/dist/types/src/components/ChannelContainer.stories.d.ts.map +1 -0
  190. package/dist/types/src/components/Chat.stories.d.ts.map +1 -1
  191. package/dist/types/src/components/ChatContainer.d.ts +9 -7
  192. package/dist/types/src/components/ChatContainer.d.ts.map +1 -1
  193. package/dist/types/src/components/CommentContainer.d.ts +11 -2
  194. package/dist/types/src/components/CommentContainer.d.ts.map +1 -1
  195. package/dist/types/src/components/Comments.stories.d.ts +1 -1
  196. package/dist/types/src/components/Comments.stories.d.ts.map +1 -1
  197. package/dist/types/src/components/CommentsContainer.d.ts +5 -9
  198. package/dist/types/src/components/CommentsContainer.d.ts.map +1 -1
  199. package/dist/types/src/components/Lobby/Lobby.d.ts +15 -0
  200. package/dist/types/src/components/Lobby/Lobby.d.ts.map +1 -0
  201. package/dist/types/src/components/Lobby/index.d.ts +2 -0
  202. package/dist/types/src/components/Lobby/index.d.ts.map +1 -0
  203. package/dist/types/src/components/Media/AudioStream.d.ts +6 -0
  204. package/dist/types/src/components/Media/AudioStream.d.ts.map +1 -0
  205. package/dist/types/src/components/Media/VideoObject.d.ts +15 -0
  206. package/dist/types/src/components/Media/VideoObject.d.ts.map +1 -0
  207. package/dist/types/src/components/Media/VideoObject.stories.d.ts +8 -0
  208. package/dist/types/src/components/Media/VideoObject.stories.d.ts.map +1 -0
  209. package/dist/types/src/components/Media/index.d.ts +3 -0
  210. package/dist/types/src/components/Media/index.d.ts.map +1 -0
  211. package/dist/types/src/components/MessageContainer.d.ts +5 -4
  212. package/dist/types/src/components/MessageContainer.d.ts.map +1 -1
  213. package/dist/types/src/components/Participant/Participant.d.ts +6 -0
  214. package/dist/types/src/components/Participant/Participant.d.ts.map +1 -0
  215. package/dist/types/src/components/Participant/ParticipantGrid.d.ts +11 -0
  216. package/dist/types/src/components/Participant/ParticipantGrid.d.ts.map +1 -0
  217. package/dist/types/src/components/Participant/index.d.ts +3 -0
  218. package/dist/types/src/components/Participant/index.d.ts.map +1 -0
  219. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.d.ts +12 -0
  220. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.d.ts.map +1 -0
  221. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts +10 -0
  222. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts.map +1 -0
  223. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.d.ts +32 -0
  224. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.d.ts.map +1 -0
  225. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts +23 -0
  226. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts.map +1 -0
  227. package/dist/types/src/components/ResponsiveGrid/ResponsiveGridItem.d.ts +21 -0
  228. package/dist/types/src/components/ResponsiveGrid/ResponsiveGridItem.d.ts.map +1 -0
  229. package/dist/types/src/components/ResponsiveGrid/index.d.ts +4 -0
  230. package/dist/types/src/components/ResponsiveGrid/index.d.ts.map +1 -0
  231. package/dist/types/src/components/ThreadComplementary.d.ts.map +1 -1
  232. package/dist/types/src/components/ThreadSettings.d.ts.map +1 -1
  233. package/dist/types/src/components/index.d.ts +5 -1
  234. package/dist/types/src/components/index.d.ts.map +1 -1
  235. package/dist/types/src/components/testing.d.ts +101 -54
  236. package/dist/types/src/components/testing.d.ts.map +1 -1
  237. package/dist/types/src/extensions/threads.d.ts.map +1 -1
  238. package/dist/types/src/hooks/analytics.d.ts +3 -3
  239. package/dist/types/src/hooks/analytics.d.ts.map +1 -1
  240. package/dist/types/src/hooks/index.d.ts +2 -1
  241. package/dist/types/src/hooks/index.d.ts.map +1 -1
  242. package/dist/types/src/hooks/useDebugMode.d.ts +2 -0
  243. package/dist/types/src/hooks/useDebugMode.d.ts.map +1 -0
  244. package/dist/types/src/hooks/useStatus.d.ts.map +1 -1
  245. package/dist/types/src/index.d.ts +1 -1
  246. package/dist/types/src/index.d.ts.map +1 -1
  247. package/dist/types/src/meta.d.ts.map +1 -1
  248. package/dist/types/src/peers.stories.d.ts +11 -0
  249. package/dist/types/src/peers.stories.d.ts.map +1 -0
  250. package/dist/types/src/testing/index.d.ts +2 -0
  251. package/dist/types/src/testing/index.d.ts.map +1 -0
  252. package/dist/types/src/testing/stories.d.ts +2 -0
  253. package/dist/types/src/testing/stories.d.ts.map +1 -0
  254. package/dist/types/src/translations.d.ts +35 -56
  255. package/dist/types/src/translations.d.ts.map +1 -1
  256. package/dist/types/src/types/index.d.ts +3 -0
  257. package/dist/types/src/types/index.d.ts.map +1 -0
  258. package/dist/types/src/types/schema.d.ts +317 -0
  259. package/dist/types/src/types/schema.d.ts.map +1 -0
  260. package/dist/types/src/types/types.d.ts +1015 -0
  261. package/dist/types/src/types/types.d.ts.map +1 -0
  262. package/dist/types/src/util.d.ts +2 -0
  263. package/dist/types/src/util.d.ts.map +1 -1
  264. package/dist/types/tsconfig.tsbuildinfo +1 -1
  265. package/package.json +60 -40
  266. package/src/ThreadPlugin.tsx +33 -14
  267. package/src/calls/call-manager.ts +242 -0
  268. package/src/calls/call-swarm-synchronizer.ts +350 -0
  269. package/src/calls/index.ts +10 -0
  270. package/src/calls/media-manager.ts +342 -0
  271. package/src/calls/speaking-monitor.ts +85 -0
  272. package/src/calls/types.ts +70 -0
  273. package/src/calls/util/audio.ts +58 -0
  274. package/src/calls/util/calls-service.ts +527 -0
  275. package/src/calls/util/history-cache.ts +27 -0
  276. package/src/calls/util/index.ts +8 -0
  277. package/src/calls/util/media.ts +52 -0
  278. package/src/calls/util/stub-media-streams.ts +73 -0
  279. package/src/calls/util/task-scheduling.ts +92 -0
  280. package/src/capabilities/app-graph-builder.ts +171 -25
  281. package/src/capabilities/call-manager.ts +19 -0
  282. package/src/capabilities/capabilities.ts +15 -1
  283. package/src/capabilities/index.ts +2 -0
  284. package/src/capabilities/intent-resolver.ts +77 -56
  285. package/src/capabilities/markdown.ts +54 -4
  286. package/src/capabilities/react-root.tsx +17 -0
  287. package/src/capabilities/react-surface.tsx +52 -27
  288. package/src/capabilities/settings.ts +2 -2
  289. package/src/capabilities/state.ts +3 -3
  290. package/src/components/Call/Call.tsx +88 -0
  291. package/src/components/Call/Toolbar.tsx +182 -0
  292. package/src/components/Call/index.ts +6 -0
  293. package/src/components/CallDebugPanel.tsx +115 -0
  294. package/src/components/CallSidebar.tsx +17 -0
  295. package/src/components/ChannelContainer.stories.tsx +58 -0
  296. package/src/components/ChannelContainer.tsx +203 -0
  297. package/src/components/Chat.stories.tsx +11 -12
  298. package/src/components/ChatContainer.tsx +37 -25
  299. package/src/components/CommentContainer.tsx +56 -61
  300. package/src/components/Comments.stories.tsx +20 -16
  301. package/src/components/CommentsContainer.tsx +20 -36
  302. package/src/components/Lobby/Lobby.tsx +119 -0
  303. package/src/components/Lobby/index.ts +5 -0
  304. package/src/components/Media/AudioStream.tsx +67 -0
  305. package/src/components/Media/VideoObject.stories.tsx +52 -0
  306. package/src/components/Media/VideoObject.tsx +58 -0
  307. package/src/components/Media/index.ts +6 -0
  308. package/src/components/MessageContainer.tsx +31 -50
  309. package/src/components/Participant/Participant.tsx +57 -0
  310. package/src/components/Participant/ParticipantGrid.tsx +88 -0
  311. package/src/components/Participant/index.ts +6 -0
  312. package/src/components/ResponsiveGrid/ResponsiveContainer.stories.tsx +54 -0
  313. package/src/components/ResponsiveGrid/ResponsiveContainer.tsx +31 -0
  314. package/src/components/ResponsiveGrid/ResponsiveGrid.stories.tsx +156 -0
  315. package/src/components/ResponsiveGrid/ResponsiveGrid.tsx +341 -0
  316. package/src/components/ResponsiveGrid/ResponsiveGridItem.tsx +131 -0
  317. package/src/components/ResponsiveGrid/index.ts +7 -0
  318. package/src/components/ThreadComplementary.tsx +37 -42
  319. package/src/components/index.ts +4 -0
  320. package/src/components/testing.ts +6 -5
  321. package/src/extensions/threads.ts +42 -24
  322. package/src/hooks/analytics.ts +4 -4
  323. package/src/hooks/index.ts +2 -1
  324. package/src/hooks/useDebugMode.ts +25 -0
  325. package/src/index.ts +1 -1
  326. package/src/meta.ts +4 -3
  327. package/src/peers.stories.tsx +189 -0
  328. package/src/testing/index.ts +5 -0
  329. package/src/testing/stories.ts +50 -0
  330. package/src/translations.ts +46 -5
  331. package/src/types/index.ts +6 -0
  332. package/src/types/schema.ts +29 -0
  333. package/src/types/types.ts +110 -0
  334. package/src/typings/peermetrics-webrtc-stats.d.ts +30 -0
  335. package/src/util.ts +12 -0
  336. package/dist/lib/browser/ChatContainer-IOOAQW6S.mjs +0 -138
  337. package/dist/lib/browser/ChatContainer-IOOAQW6S.mjs.map +0 -7
  338. package/dist/lib/browser/app-graph-builder-6W4UKJDI.mjs +0 -41
  339. package/dist/lib/browser/app-graph-builder-6W4UKJDI.mjs.map +0 -7
  340. package/dist/lib/browser/chunk-EP6MRLY7.mjs.map +0 -7
  341. package/dist/lib/browser/chunk-QDJ3Y6WF.mjs.map +0 -7
  342. package/dist/lib/browser/chunk-S5ZR4FYW.mjs +0 -17
  343. package/dist/lib/browser/chunk-S5ZR4FYW.mjs.map +0 -7
  344. package/dist/lib/browser/chunk-TFVPUPOO.mjs +0 -207
  345. package/dist/lib/browser/chunk-TFVPUPOO.mjs.map +0 -7
  346. package/dist/lib/browser/chunk-WBJLUUOK.mjs.map +0 -7
  347. package/dist/lib/browser/chunk-WOG72DWE.mjs +0 -93
  348. package/dist/lib/browser/chunk-WOG72DWE.mjs.map +0 -7
  349. package/dist/lib/browser/intent-resolver-QAY4FLLM.mjs.map +0 -7
  350. package/dist/lib/browser/markdown-7KXBXCUS.mjs +0 -111
  351. package/dist/lib/browser/markdown-7KXBXCUS.mjs.map +0 -7
  352. package/dist/lib/browser/react-surface-MT3OWULR.mjs +0 -437
  353. package/dist/lib/browser/react-surface-MT3OWULR.mjs.map +0 -7
  354. package/dist/lib/browser/settings-4FEC7EAX.mjs.map +0 -7
  355. package/dist/lib/browser/state-PNMSLKAH.mjs.map +0 -7
  356. package/dist/lib/browser/types.mjs +0 -10
  357. package/dist/lib/node/ChatContainer-4FNDRF3G.cjs +0 -163
  358. package/dist/lib/node/ChatContainer-4FNDRF3G.cjs.map +0 -7
  359. package/dist/lib/node/app-graph-builder-HZNWT4QU.cjs +0 -57
  360. package/dist/lib/node/app-graph-builder-HZNWT4QU.cjs.map +0 -7
  361. package/dist/lib/node/chunk-46BSFPBV.cjs +0 -113
  362. package/dist/lib/node/chunk-46BSFPBV.cjs.map +0 -7
  363. package/dist/lib/node/chunk-AKINTFBH.cjs.map +0 -7
  364. package/dist/lib/node/chunk-E7Z3BKRQ.cjs +0 -232
  365. package/dist/lib/node/chunk-E7Z3BKRQ.cjs.map +0 -7
  366. package/dist/lib/node/chunk-NQ5DTPOY.cjs.map +0 -7
  367. package/dist/lib/node/chunk-S2A6BXEA.cjs.map +0 -7
  368. package/dist/lib/node/intent-resolver-S6FE5OR7.cjs.map +0 -7
  369. package/dist/lib/node/markdown-L2WMCQKM.cjs +0 -121
  370. package/dist/lib/node/markdown-L2WMCQKM.cjs.map +0 -7
  371. package/dist/lib/node/react-surface-Z45BYECE.cjs +0 -439
  372. package/dist/lib/node/react-surface-Z45BYECE.cjs.map +0 -7
  373. package/dist/lib/node/settings-IXCPE55J.cjs.map +0 -7
  374. package/dist/lib/node/state-AT73KPGZ.cjs.map +0 -7
  375. package/dist/lib/node/types.cjs.map +0 -7
  376. package/dist/lib/node-esm/ChatContainer-NYLCL6QA.mjs +0 -139
  377. package/dist/lib/node-esm/ChatContainer-NYLCL6QA.mjs.map +0 -7
  378. package/dist/lib/node-esm/app-graph-builder-M3KK5QJH.mjs +0 -42
  379. package/dist/lib/node-esm/app-graph-builder-M3KK5QJH.mjs.map +0 -7
  380. package/dist/lib/node-esm/chunk-42F2DTMM.mjs.map +0 -7
  381. package/dist/lib/node-esm/chunk-ADTVMESP.mjs +0 -208
  382. package/dist/lib/node-esm/chunk-ADTVMESP.mjs.map +0 -7
  383. package/dist/lib/node-esm/chunk-E446MGLP.mjs +0 -94
  384. package/dist/lib/node-esm/chunk-E446MGLP.mjs.map +0 -7
  385. package/dist/lib/node-esm/chunk-J56FORYF.mjs.map +0 -7
  386. package/dist/lib/node-esm/chunk-WLY2HMDB.mjs.map +0 -7
  387. package/dist/lib/node-esm/chunk-WSE23GSG.mjs +0 -19
  388. package/dist/lib/node-esm/chunk-WSE23GSG.mjs.map +0 -7
  389. package/dist/lib/node-esm/intent-resolver-OURFRSSF.mjs.map +0 -7
  390. package/dist/lib/node-esm/markdown-ZKU23UVD.mjs +0 -112
  391. package/dist/lib/node-esm/markdown-ZKU23UVD.mjs.map +0 -7
  392. package/dist/lib/node-esm/react-surface-KIJ767JK.mjs +0 -438
  393. package/dist/lib/node-esm/react-surface-KIJ767JK.mjs.map +0 -7
  394. package/dist/lib/node-esm/settings-ZUJQ4LWI.mjs.map +0 -7
  395. package/dist/lib/node-esm/state-SSDX5O67.mjs.map +0 -7
  396. package/dist/lib/node-esm/types.mjs +0 -11
  397. package/dist/types/src/components/types.d.ts +0 -28
  398. package/dist/types/src/components/types.d.ts.map +0 -1
  399. package/dist/types/src/events.d.ts +0 -4
  400. package/dist/types/src/events.d.ts.map +0 -1
  401. package/dist/types/src/types.d.ts +0 -125
  402. package/dist/types/src/types.d.ts.map +0 -1
  403. package/src/components/types.ts +0 -32
  404. package/src/events.ts +0 -11
  405. package/src/types.ts +0 -100
  406. /package/dist/lib/browser/{types.mjs.map → ChannelContainer-LGYSQMC7.mjs.map} +0 -0
  407. /package/dist/lib/{node-esm/types.mjs.map → browser/ChatContainer-JWRI73OG.mjs.map} +0 -0
@@ -5,21 +5,18 @@
5
5
  import { ChatText } from '@phosphor-icons/react';
6
6
  import React, { useEffect } from 'react';
7
7
 
8
- import { type ThreadType } from '@dxos/plugin-space/types';
8
+ import { RelationSourceId } from '@dxos/echo-schema';
9
9
  import { fullyQualifiedId } from '@dxos/react-client/echo';
10
10
  import { useTranslation, Trans } from '@dxos/react-ui';
11
- import { descriptionText, mx } from '@dxos/react-ui-theme';
11
+ import { descriptionMessage, mx } from '@dxos/react-ui-theme';
12
+ import { type AnchoredTo } from '@dxos/schema';
12
13
 
13
- import { CommentContainer } from './CommentContainer';
14
- import { type ThreadContainerProps } from './types';
14
+ import { CommentContainer, type CommentContainerProps } from './CommentContainer';
15
15
  import { THREAD_PLUGIN } from '../meta';
16
+ import { type ThreadType } from '../types';
16
17
 
17
- export type ThreadsContainerProps = Omit<ThreadContainerProps, 'thread' | 'detached' | 'current' | 'autoFocus'> & {
18
- threads: ThreadType[];
19
- /**
20
- * Threads that are no longer anchored to a position in the object.
21
- */
22
- detached?: string[];
18
+ export type ThreadsContainerProps = Omit<CommentContainerProps, 'anchor' | 'current'> & {
19
+ anchors: AnchoredTo[];
23
20
  currentId?: string;
24
21
  showResolvedThreads?: boolean;
25
22
  };
@@ -27,15 +24,15 @@ export type ThreadsContainerProps = Omit<ThreadContainerProps, 'thread' | 'detac
27
24
  /**
28
25
  * Comment threads.
29
26
  */
30
- export const CommentsContainer = ({
31
- threads,
32
- detached = [],
33
- currentId,
34
- showResolvedThreads,
35
- ...props
36
- }: ThreadsContainerProps) => {
27
+ export const CommentsContainer = ({ anchors, currentId, showResolvedThreads, ...props }: ThreadsContainerProps) => {
37
28
  const { t } = useTranslation(THREAD_PLUGIN);
38
- const filteredThreads = showResolvedThreads ? threads : threads.filter((thread) => !(thread?.status === 'resolved'));
29
+ // TODO(wittjosiah): There seems to be a race between thread and anchor being deleted.
30
+ const filteredAnchors = showResolvedThreads
31
+ ? anchors.filter((anchor) => !!anchor[RelationSourceId])
32
+ : anchors.filter((anchor) => {
33
+ const thread = anchor[RelationSourceId];
34
+ return thread && thread.status !== 'resolved';
35
+ });
39
36
 
40
37
  useEffect(() => {
41
38
  if (currentId) {
@@ -45,27 +42,14 @@ export const CommentsContainer = ({
45
42
 
46
43
  return (
47
44
  <>
48
- {filteredThreads.length > 0 ? (
49
- filteredThreads.map((thread) => {
45
+ {filteredAnchors.length > 0 ? (
46
+ filteredAnchors.map((anchor) => {
47
+ const thread = anchor[RelationSourceId] as ThreadType;
50
48
  const threadId = fullyQualifiedId(thread);
51
- return (
52
- <CommentContainer
53
- key={threadId}
54
- thread={thread}
55
- current={currentId === threadId}
56
- detached={detached.includes(threadId)}
57
- {...props}
58
- />
59
- );
49
+ return <CommentContainer key={threadId} anchor={anchor} current={currentId === threadId} {...props} />;
60
50
  })
61
51
  ) : (
62
- <div
63
- role='alert'
64
- className={mx(
65
- descriptionText,
66
- 'place-self-center border border-dashed border-unAccent rounded-lg text-center p-4 m-4',
67
- )}
68
- >
52
+ <div role='alert' className={mx(descriptionMessage, 'place-self-center rounded-lg text-center m-4')}>
69
53
  <h2 className='mbe-2 font-medium text-baseText'>{t('no comments title')}</h2>
70
54
  <p>
71
55
  <Trans
@@ -0,0 +1,119 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { type FC, type PropsWithChildren, useEffect, useState } from 'react';
6
+
7
+ import { useCapability } from '@dxos/app-framework';
8
+ import { useTranslation, type ThemedClassName } from '@dxos/react-ui';
9
+ import { mx } from '@dxos/react-ui-theme';
10
+
11
+ import { ThreadCapabilities } from '../../capabilities';
12
+ import { meta } from '../../meta';
13
+ import { Toolbar, type ToolbarProps } from '../Call';
14
+ import { VideoObject } from '../Media';
15
+ import { ResponsiveContainer } from '../ResponsiveGrid';
16
+
17
+ // TODO(wittjosiah): Repurpose lobby for preview.
18
+
19
+ const SWARM_PEEK_INTERVAL = 1_000;
20
+
21
+ //
22
+ // Root
23
+ //
24
+
25
+ type LobbyRootProps = PropsWithChildren<ThemedClassName>;
26
+
27
+ const LobbyRoot: FC<LobbyRootProps> = ({ children }) => {
28
+ return <div className='relative flex flex-col grow overflow-hidden group'>{children}</div>;
29
+ };
30
+
31
+ LobbyRoot.displayName = 'LobbyRoot';
32
+
33
+ //
34
+ // Preview
35
+ //
36
+
37
+ type LobbyPreviewProps = {};
38
+
39
+ const LobbyPreview: FC<LobbyPreviewProps> = () => {
40
+ const { t } = useTranslation(meta.id);
41
+ const call = useCapability(ThreadCapabilities.CallManager);
42
+ const [classNames, setClassNames] = useState('');
43
+ useEffect(() => {
44
+ if (!call.media.videoEnabled) {
45
+ setClassNames('');
46
+ return;
47
+ }
48
+
49
+ // Video element will expand once the stream is available.
50
+ const timeout = setTimeout(() => {
51
+ setClassNames('outline-neutral-900 opacity-100');
52
+ }, 500);
53
+
54
+ return () => clearTimeout(timeout);
55
+ }, [call.media.videoEnabled]);
56
+
57
+ return (
58
+ <div className='grid grow p-4'>
59
+ <ResponsiveContainer>
60
+ {(call.media.videoEnabled && (
61
+ <VideoObject
62
+ videoStream={call.media.videoStream}
63
+ flip
64
+ muted
65
+ classNames={mx(
66
+ 'rounded-md outline outline-2 outline-transparent opacity-0 transition-all duration-500',
67
+ classNames,
68
+ )}
69
+ />
70
+ )) || <div className='p-4 outline outline-separator rounded-md'>{t('camera off label')}</div>}
71
+ </ResponsiveContainer>
72
+ </div>
73
+ );
74
+ };
75
+
76
+ LobbyPreview.displayName = 'LobbyPreview';
77
+
78
+ //
79
+ // Toolbar
80
+ //
81
+
82
+ type LobbyToolbarProps = ThemedClassName<
83
+ {
84
+ roomId: string;
85
+ } & Pick<ToolbarProps, 'onJoin'>
86
+ >;
87
+
88
+ const LobbyToolbar: FC<LobbyToolbarProps> = ({ roomId, ...props }) => {
89
+ const call = useCapability(ThreadCapabilities.CallManager);
90
+ const [count, setCount] = useState<number>(0);
91
+
92
+ // TODO(wittjosiah): Leaving the room doesn't remove you from the swarm.
93
+ useEffect(() => {
94
+ void call.peek(roomId).then((count) => setCount(count));
95
+ const interval = setInterval(() => {
96
+ void call.peek(roomId).then((count) => setCount(count));
97
+ }, SWARM_PEEK_INTERVAL);
98
+
99
+ return () => clearInterval(interval);
100
+ }, [call, roomId]);
101
+
102
+ return (
103
+ <div className='absolute bottom-0 left-0 right-0 flex justify-center'>
104
+ <Toolbar participants={count} isInRoom={false} {...props} />
105
+ </div>
106
+ );
107
+ };
108
+
109
+ LobbyToolbar.displayName = 'LobbyToolbar';
110
+
111
+ //
112
+ // Export
113
+ //
114
+
115
+ export const Lobby = {
116
+ Root: LobbyRoot,
117
+ Preview: LobbyPreview,
118
+ Toolbar: LobbyToolbar,
119
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './Lobby';
@@ -0,0 +1,67 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { type FC, useEffect, useRef } from 'react';
6
+
7
+ export type AudioStreamProps = {
8
+ tracks: MediaStreamTrack[];
9
+ };
10
+
11
+ export const AudioStream: FC<AudioStreamProps> = ({ tracks }) => {
12
+ const mediaStreamRef = useRef(new MediaStream());
13
+ const ref = useRef<HTMLAudioElement>(null);
14
+
15
+ useEffect(() => {
16
+ const audio = ref.current;
17
+ if (!audio) {
18
+ return;
19
+ }
20
+
21
+ const mediaStream = mediaStreamRef.current;
22
+ audio.srcObject = mediaStream;
23
+ }, []);
24
+
25
+ const resetSrcObject = () => {
26
+ const audio = ref.current;
27
+ const mediaStream = mediaStreamRef.current;
28
+ if (!audio || !mediaStream) {
29
+ return;
30
+ }
31
+
32
+ // Need to set srcObject again in Chrome and call play() again for Safari
33
+ // https://www.youtube.com/live/Tkx3OGrwVk8?si=K--P_AzNnAGrjraV&t=2533
34
+ // Calling play() this way to make Chrome happy otherwise it throws an error.
35
+ audio.addEventListener('canplay', () => audio.play(), { once: true });
36
+ audio.srcObject = mediaStream;
37
+ };
38
+
39
+ return (
40
+ <>
41
+ <audio ref={ref} autoPlay />
42
+ {tracks.map((track) => (
43
+ <AudioTrack key={track.id} track={track} mediaStream={mediaStreamRef.current} resetSrcObject={resetSrcObject} />
44
+ ))}
45
+ </>
46
+ );
47
+ };
48
+
49
+ type AudioTrackProps = {
50
+ track: MediaStreamTrack;
51
+ mediaStream: MediaStream;
52
+ resetSrcObject: () => void;
53
+ };
54
+
55
+ const AudioTrack = ({ track, mediaStream, resetSrcObject }: AudioTrackProps) => {
56
+ useEffect(() => {
57
+ const currentTrack = track;
58
+ mediaStream.addTrack(currentTrack);
59
+ resetSrcObject();
60
+ return () => {
61
+ mediaStream.removeTrack(currentTrack);
62
+ resetSrcObject();
63
+ };
64
+ }, [track, mediaStream]);
65
+
66
+ return null;
67
+ };
@@ -0,0 +1,52 @@
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, useState } from 'react';
9
+
10
+ import { scheduleTask } from '@dxos/async';
11
+ import { Context } from '@dxos/context';
12
+ import { log } from '@dxos/log';
13
+ import { withTheme, withLayout } from '@dxos/storybook-utils';
14
+
15
+ import { VideoObject } from './VideoObject';
16
+ import { getUserMediaTrack } from '../../calls';
17
+ import { ResponsiveContainer } from '../ResponsiveGrid';
18
+
19
+ const meta: Meta<typeof VideoObject> = {
20
+ title: 'plugins/plugin-thread/VideoObject',
21
+ component: VideoObject,
22
+ render: (args) => {
23
+ log.info('render');
24
+ const [videoStream, setVideoStream] = useState<MediaStream>();
25
+ useEffect(() => {
26
+ const ctx = new Context();
27
+ scheduleTask(ctx, async () => {
28
+ const stream = new MediaStream();
29
+ stream.addTrack(await getUserMediaTrack('videoinput'));
30
+ setVideoStream(stream);
31
+ });
32
+
33
+ return () => {
34
+ void ctx.dispose();
35
+ videoStream?.getTracks().forEach((track) => track.stop());
36
+ };
37
+ }, []);
38
+
39
+ return (
40
+ <ResponsiveContainer>
41
+ <VideoObject videoStream={videoStream} {...args} flip />
42
+ </ResponsiveContainer>
43
+ );
44
+ },
45
+ decorators: [withTheme, withLayout({ fullscreen: true, classNames: 'justify-center' })],
46
+ };
47
+
48
+ export default meta;
49
+
50
+ type Story = StoryObj<typeof VideoObject>;
51
+
52
+ export const SelfView: Story = {};
@@ -0,0 +1,58 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { type JSX, forwardRef, memo, useEffect, useRef } from 'react';
6
+
7
+ import { type ThemedClassName } from '@dxos/react-ui';
8
+ import { mx } from '@dxos/react-ui-theme';
9
+
10
+ export type VideoObjectProps = Omit<JSX.IntrinsicElements['video'], 'className' | 'ref'> &
11
+ ThemedClassName<{
12
+ videoStream?: MediaStream;
13
+ flip?: boolean;
14
+ // TODO(burdon): If screenshare then contain.
15
+ contain?: boolean;
16
+ }>;
17
+
18
+ export const VideoObject = memo(
19
+ forwardRef<HTMLVideoElement, VideoObjectProps>(({ videoStream, classNames, flip, contain, ...rest }, ref) => {
20
+ const internalRef = useRef<HTMLVideoElement | null>(null);
21
+
22
+ useEffect(() => {
23
+ const video = internalRef.current;
24
+ if (video && videoStream) {
25
+ video.srcObject = videoStream;
26
+ video.setAttribute('autoplay', 'true');
27
+ video.setAttribute('playsinline', 'true');
28
+ }
29
+ }, [videoStream, internalRef.current]);
30
+
31
+ // NOTE: The video element typically has a max size of 1280x720.
32
+ return (
33
+ <video
34
+ className={mx(
35
+ 'w-full aspect-video',
36
+ flip && 'scale-x-[-1]',
37
+ contain ? 'object-contain' : 'object-cover',
38
+ classNames,
39
+ )}
40
+ ref={(v) => {
41
+ internalRef.current = v;
42
+ if (ref === null) {
43
+ return;
44
+ }
45
+
46
+ if (typeof ref === 'function') {
47
+ ref(v);
48
+ } else {
49
+ ref.current = v;
50
+ }
51
+ }}
52
+ {...rest}
53
+ />
54
+ );
55
+ }),
56
+ );
57
+
58
+ VideoObject.displayName = 'VideoObject';
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './AudioStream';
6
+ export * from './VideoObject';
@@ -9,7 +9,7 @@ import React, { forwardRef, useCallback, useEffect, useRef, useState } from 'rea
9
9
  import { Surface } from '@dxos/app-framework';
10
10
  import { RefArray } from '@dxos/live-object';
11
11
  import { PublicKey } from '@dxos/react-client';
12
- import { type ReactiveEchoObject, type Expando, type SpaceMember } from '@dxos/react-client/echo';
12
+ import { type AnyLiveObject, type Expando, type SpaceMember } from '@dxos/react-client/echo';
13
13
  import { useIdentity, type Identity } from '@dxos/react-client/halo';
14
14
  import { Button, ButtonGroup, Tooltip, useOnTransition, useThemeContext, useTranslation } from '@dxos/react-ui';
15
15
  import { createBasicExtensions, createThemeExtensions, useTextEditor } from '@dxos/react-ui-editor';
@@ -21,7 +21,7 @@ import {
21
21
  mx,
22
22
  } from '@dxos/react-ui-theme';
23
23
  import { MessageHeading, MessageRoot } from '@dxos/react-ui-thread';
24
- import { type TextContentBlock, type MessageType } from '@dxos/schema';
24
+ import { type DataType } from '@dxos/schema';
25
25
 
26
26
  import { command } from './command-extension';
27
27
  import { useOnEditAnalytics } from '../hooks';
@@ -31,17 +31,14 @@ import { getMessageMetadata } from '../util';
31
31
  // TODO(thure): #8149
32
32
  const messageControlClassNames = ['!p-1 !min-bs-0 transition-opacity', hoverableControlItem];
33
33
 
34
- export const MessageContainer = ({
35
- message,
36
- members,
37
- editable = false,
38
- onDelete,
39
- }: {
40
- message: MessageType;
34
+ export type MessageContainerProps = {
35
+ message: DataType.Message;
41
36
  members: SpaceMember[];
42
37
  editable?: boolean;
43
38
  onDelete?: (id: string) => void;
44
- }) => {
39
+ };
40
+
41
+ export const MessageContainer = ({ message, members, editable = false, onDelete }: MessageContainerProps) => {
45
42
  const senderIdentity = members.find(
46
43
  (member) =>
47
44
  (message.sender.identityDid && member.identity.did === message.sender.identityDid) ||
@@ -64,46 +61,30 @@ export const MessageContainer = ({
64
61
  <MessageHeading authorName={messageMetadata.authorName} timestamp={messageMetadata.timestamp}>
65
62
  <ButtonGroup classNames='mie-1'>
66
63
  {userIsAuthor && editable && (
67
- <Tooltip.Root>
68
- <Tooltip.Trigger asChild>
69
- <Button
70
- variant='ghost'
71
- data-testid={editing ? 'thread.message.save' : 'thread.message.edit'}
72
- classNames={messageControlClassNames}
73
- onClick={() => setEditing((editing) => !editing)}
74
- >
75
- <span className='sr-only'>{editLabel}</span>
76
- {editing ? <Check className={getSize(4)} /> : <PencilSimple className={getSize(4)} />}
77
- </Button>
78
- </Tooltip.Trigger>
79
- <Tooltip.Portal>
80
- <Tooltip.Content>
81
- {editLabel}
82
- <Tooltip.Arrow />
83
- </Tooltip.Content>
84
- </Tooltip.Portal>
85
- </Tooltip.Root>
64
+ <Tooltip.Trigger asChild content={editLabel}>
65
+ <Button
66
+ variant='ghost'
67
+ data-testid={editing ? 'thread.message.save' : 'thread.message.edit'}
68
+ classNames={messageControlClassNames}
69
+ onClick={() => setEditing((editing) => !editing)}
70
+ >
71
+ <span className='sr-only'>{editLabel}</span>
72
+ {editing ? <Check className={getSize(4)} /> : <PencilSimple className={getSize(4)} />}
73
+ </Button>
74
+ </Tooltip.Trigger>
86
75
  )}
87
76
  {onDelete && (
88
- <Tooltip.Root>
89
- <Tooltip.Trigger asChild>
90
- <Button
91
- variant='ghost'
92
- data-testid='thread.message.delete'
93
- classNames={messageControlClassNames}
94
- onClick={() => handleDelete()}
95
- >
96
- <span className='sr-only'>{deleteLabel}</span>
97
- <X className={getSize(4)} />
98
- </Button>
99
- </Tooltip.Trigger>
100
- <Tooltip.Portal>
101
- <Tooltip.Content>
102
- {deleteLabel}
103
- <Tooltip.Arrow />
104
- </Tooltip.Content>
105
- </Tooltip.Portal>
106
- </Tooltip.Root>
77
+ <Tooltip.Trigger asChild content={deleteLabel}>
78
+ <Button
79
+ variant='ghost'
80
+ data-testid='thread.message.delete'
81
+ classNames={messageControlClassNames}
82
+ onClick={() => handleDelete()}
83
+ >
84
+ <span className='sr-only'>{deleteLabel}</span>
85
+ <X className={getSize(4)} />
86
+ </Button>
87
+ </Tooltip.Trigger>
107
88
  )}
108
89
  </ButtonGroup>
109
90
  </MessageHeading>
@@ -124,7 +105,7 @@ const TextboxBlock = ({
124
105
  isAuthor,
125
106
  editing,
126
107
  }: {
127
- block: TextContentBlock;
108
+ block: DataType.MessageBlock.Text;
128
109
  editing?: boolean;
129
110
  isAuthor?: boolean;
130
111
  identity?: Identity;
@@ -166,7 +147,7 @@ const TextboxBlock = ({
166
147
  return <div role='none' ref={parentRef} className='mie-4' {...focusAttributes} />;
167
148
  };
168
149
 
169
- const MessageBlockObjectTile = forwardRef<HTMLDivElement, { subject: ReactiveEchoObject<any> }>(
150
+ const MessageBlockObjectTile = forwardRef<HTMLDivElement, { subject: AnyLiveObject<any> }>(
170
151
  ({ subject }, forwardedRef) => {
171
152
  let title = subject.name ?? subject.title ?? subject.type ?? 'Object';
172
153
  if (typeof title !== 'string') {
@@ -0,0 +1,57 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { memo, useMemo } from 'react';
6
+
7
+ import { useCapability } from '@dxos/app-framework';
8
+
9
+ import { type EncodedTrackName, type UserState } from '../../calls';
10
+ import { ThreadCapabilities } from '../../capabilities';
11
+ import { VideoObject } from '../Media';
12
+ import { ResponsiveGridItem, type ResponsiveGridItemProps } from '../ResponsiveGrid';
13
+
14
+ export const SCREENSHARE_SUFFIX = '_screenshare';
15
+
16
+ export const Participant = memo(({ item: user, debug, ...props }: ResponsiveGridItemProps<UserState>) => {
17
+ const call = useCapability(ThreadCapabilities.CallManager);
18
+ const isSelf: boolean = call.self.id !== undefined && user.id !== undefined && user.id.startsWith(call.self.id);
19
+ const isScreenshare = user.id?.endsWith(SCREENSHARE_SUFFIX);
20
+ const pulledVideoStream = call.getVideoStream(
21
+ isScreenshare || !isSelf ? (user.tracks?.video as EncodedTrackName) : undefined,
22
+ );
23
+
24
+ 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
+ } else if (!isSelf) {
30
+ return pulledVideoStream;
31
+ }
32
+ }, [isSelf, isScreenshare, call.media.videoStream, call.media.screenshareVideoStream, pulledVideoStream]);
33
+
34
+ return (
35
+ <ResponsiveGridItem
36
+ {...props}
37
+ item={user}
38
+ name={user.name}
39
+ self={isSelf}
40
+ screenshare={!!call.media.screenshareVideoStream}
41
+ video={call.media.videoEnabled}
42
+ mute={user ? !user.tracks?.audioEnabled : false}
43
+ wave={user.raisedHand}
44
+ speaking={user.speaking}
45
+ debug={debug}
46
+ >
47
+ <VideoObject
48
+ videoStream={videoStream}
49
+ flip={isSelf && !isScreenshare}
50
+ contain={!!isScreenshare}
51
+ classNames='rounded-md'
52
+ />
53
+ </ResponsiveGridItem>
54
+ );
55
+ });
56
+
57
+ Participant.displayName = 'Participant';
@@ -0,0 +1,88 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, { useEffect, useMemo, useState } from 'react';
6
+
7
+ import { type ThemedClassName } from '@dxos/react-ui';
8
+
9
+ import { Participant, SCREENSHARE_SUFFIX } from './Participant';
10
+ import { type UserState } from '../../calls';
11
+ import { ResponsiveGrid } from '../ResponsiveGrid';
12
+
13
+ const getId = (user: UserState): string => user.id!;
14
+
15
+ export type ParticipantGridProps = ThemedClassName<{
16
+ self: UserState;
17
+ users: UserState[];
18
+ fullscreen?: boolean;
19
+ debug?: boolean;
20
+ }>;
21
+
22
+ export const ParticipantGrid = ({ classNames, self, users, fullscreen, debug }: ParticipantGridProps) => {
23
+ const [pinned, setPinned] = useState<string | undefined>();
24
+
25
+ const allUsers = useMemo(() => {
26
+ const allUsers: (UserState & { isSelf?: boolean })[] = [];
27
+ users.forEach((user) => {
28
+ if (!user.joined) {
29
+ return;
30
+ }
31
+
32
+ allUsers.push({ ...user, isSelf: user.id === self.id });
33
+ if (user.tracks?.screenshareEnabled) {
34
+ const screenshare: UserState = {
35
+ ...user,
36
+ id: user.id + SCREENSHARE_SUFFIX,
37
+ tracks: {
38
+ ...user.tracks,
39
+ video: user.tracks.screenshare,
40
+ videoEnabled: user.tracks.screenshareEnabled,
41
+ } as any, // TODO(burdon): Remove cast.
42
+ };
43
+
44
+ allUsers.push(screenshare);
45
+ }
46
+ });
47
+
48
+ return allUsers;
49
+ }, [self, users]);
50
+
51
+ useEffect(() => {
52
+ if (pinned) {
53
+ // Check expanded user is still in call.
54
+ if (!allUsers.find((user) => user.id === pinned)) {
55
+ setPinned(undefined);
56
+ }
57
+ }
58
+ }, [pinned, allUsers]);
59
+
60
+ // TODO(burdon): Put self last.
61
+ const sortedUsers: UserState[] = allUsers.sort((a, b) => {
62
+ if (a.isSelf) {
63
+ return 1;
64
+ } else if (b.isSelf) {
65
+ return -1;
66
+ } else if (a.tracks?.screenshareEnabled) {
67
+ return -1;
68
+ } else if (b.tracks?.screenshareEnabled) {
69
+ return 1;
70
+ } else {
71
+ return 0;
72
+ }
73
+ });
74
+
75
+ // TODO(burdon): Show ghost view of user for a second before leaving.
76
+ return (
77
+ <ResponsiveGrid<UserState>
78
+ classNames={classNames}
79
+ Cell={Participant}
80
+ debug={debug}
81
+ getId={getId}
82
+ items={sortedUsers}
83
+ pinned={pinned}
84
+ autoHideGallery={fullscreen}
85
+ onPinnedChange={setPinned}
86
+ />
87
+ );
88
+ };
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './Participant';
6
+ export * from './ParticipantGrid';