@dxos/plugin-thread 0.8.2-main.f11618f → 0.8.2-staging.42af850

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 (400) 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-AYNXYEKP.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-3UW6ROYT.mjs → intent-resolver-YUYZCTLF.mjs} +100 -72
  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-2VZ7S4SK.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-5EKNEH56.cjs +36 -0
  44. package/dist/lib/node/ChannelContainer-5EKNEH56.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-HV2XJW5O.cjs +37 -0
  50. package/dist/lib/node/call-manager-HV2XJW5O.cjs.map +7 -0
  51. package/dist/lib/node/chunk-44I33JDT.cjs +1731 -0
  52. package/dist/lib/node/chunk-44I33JDT.cjs.map +7 -0
  53. package/dist/lib/node/chunk-4B3PPXA6.cjs +371 -0
  54. package/dist/lib/node/chunk-4B3PPXA6.cjs.map +7 -0
  55. package/dist/lib/node/{chunk-NQ5DTPOY.cjs → chunk-4YSNVPWU.cjs} +10 -8
  56. package/dist/lib/node/chunk-4YSNVPWU.cjs.map +7 -0
  57. package/dist/lib/node/chunk-6B3M6XRE.cjs +984 -0
  58. package/dist/lib/node/chunk-6B3M6XRE.cjs.map +7 -0
  59. package/dist/lib/node/{chunk-W25MBII2.cjs → chunk-FUXJAVFZ.cjs} +50 -29
  60. package/dist/lib/node/chunk-FUXJAVFZ.cjs.map +7 -0
  61. package/dist/lib/node/{chunk-ONLWOUYZ.cjs → chunk-HLMCEE5K.cjs} +7 -7
  62. package/dist/lib/node/{chunk-ONLWOUYZ.cjs.map → chunk-HLMCEE5K.cjs.map} +2 -2
  63. package/dist/lib/node/chunk-JLHENFGK.cjs +549 -0
  64. package/dist/lib/node/chunk-JLHENFGK.cjs.map +7 -0
  65. package/dist/lib/node/chunk-LR5NENBE.cjs +54 -0
  66. package/dist/lib/node/chunk-LR5NENBE.cjs.map +7 -0
  67. package/dist/lib/node/chunk-TKHJVC2C.cjs +147 -0
  68. package/dist/lib/node/chunk-TKHJVC2C.cjs.map +7 -0
  69. package/dist/lib/node/{chunk-IX63EKGL.cjs → chunk-U7NOIXN6.cjs} +16 -10
  70. package/dist/lib/node/chunk-U7NOIXN6.cjs.map +7 -0
  71. package/dist/lib/node/index.cjs +142 -80
  72. package/dist/lib/node/index.cjs.map +4 -4
  73. package/dist/lib/node/{intent-resolver-DC6HDNTX.cjs → intent-resolver-MZ3HADNY.cjs} +108 -82
  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-IAYQ2DBO.cjs +51 -0
  79. package/dist/lib/node/react-root-IAYQ2DBO.cjs.map +7 -0
  80. package/dist/lib/node/react-surface-AVC5VVIS.cjs +122 -0
  81. package/dist/lib/node/react-surface-AVC5VVIS.cjs.map +7 -0
  82. package/dist/lib/node/{settings-7MGTJ46L.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-KFS2RWWW.mjs +16 -0
  88. package/dist/lib/node-esm/ChannelContainer-KFS2RWWW.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-UUYXLF4T.mjs +24 -0
  94. package/dist/lib/node-esm/call-manager-UUYXLF4T.mjs.map +7 -0
  95. package/dist/lib/node-esm/{chunk-42F2DTMM.mjs → chunk-ESQC6SYE.mjs} +4 -4
  96. package/dist/lib/node-esm/chunk-ESQC6SYE.mjs.map +7 -0
  97. package/dist/lib/node-esm/chunk-J323VQ4P.mjs +127 -0
  98. package/dist/lib/node-esm/chunk-J323VQ4P.mjs.map +7 -0
  99. package/dist/lib/node-esm/{chunk-WLY2HMDB.mjs → chunk-K4KAUOKT.mjs} +5 -3
  100. package/dist/lib/node-esm/chunk-K4KAUOKT.mjs.map +7 -0
  101. package/dist/lib/node-esm/chunk-MNJ3V4XM.mjs +546 -0
  102. package/dist/lib/node-esm/chunk-MNJ3V4XM.mjs.map +7 -0
  103. package/dist/lib/node-esm/{chunk-T6E5EY7Z.mjs → chunk-O3V45YJP.mjs} +57 -35
  104. package/dist/lib/node-esm/chunk-O3V45YJP.mjs.map +7 -0
  105. package/dist/lib/node-esm/chunk-ODUB4GAB.mjs +23 -0
  106. package/dist/lib/node-esm/chunk-ODUB4GAB.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-WXNPD542.mjs +1710 -0
  112. package/dist/lib/node-esm/chunk-WXNPD542.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 +107 -41
  116. package/dist/lib/node-esm/index.mjs.map +4 -4
  117. package/dist/lib/node-esm/{intent-resolver-OAMDKGAA.mjs → intent-resolver-CU22OPAH.mjs} +100 -72
  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-NQMUEI6Z.mjs +28 -0
  123. package/dist/lib/node-esm/react-root-NQMUEI6Z.mjs.map +7 -0
  124. package/dist/lib/node-esm/react-surface-Z4X5VLMY.mjs +109 -0
  125. package/dist/lib/node-esm/react-surface-Z4X5VLMY.mjs.map +7 -0
  126. package/dist/lib/node-esm/{settings-AJAZ3O47.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 +2 -179
  159. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  160. package/dist/types/src/capabilities/call-manager.d.ts +5 -0
  161. package/dist/types/src/capabilities/call-manager.d.ts.map +1 -0
  162. package/dist/types/src/capabilities/capabilities.d.ts +13 -1
  163. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  164. package/dist/types/src/capabilities/index.d.ts +8 -179
  165. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  166. package/dist/types/src/capabilities/intent-resolver.d.ts +2 -2
  167. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  168. package/dist/types/src/capabilities/markdown.d.ts +2 -2
  169. package/dist/types/src/capabilities/markdown.d.ts.map +1 -1
  170. package/dist/types/src/capabilities/react-root.d.ts +7 -0
  171. package/dist/types/src/capabilities/react-root.d.ts.map +1 -0
  172. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  173. package/dist/types/src/components/Call/Call.d.ts +17 -0
  174. package/dist/types/src/components/Call/Call.d.ts.map +1 -0
  175. package/dist/types/src/components/Call/Toolbar.d.ts +16 -0
  176. package/dist/types/src/components/Call/Toolbar.d.ts.map +1 -0
  177. package/dist/types/src/components/Call/index.d.ts +3 -0
  178. package/dist/types/src/components/Call/index.d.ts.map +1 -0
  179. package/dist/types/src/components/CallDebugPanel.d.ts +8 -0
  180. package/dist/types/src/components/CallDebugPanel.d.ts.map +1 -0
  181. package/dist/types/src/components/CallSidebar.d.ts +4 -0
  182. package/dist/types/src/components/CallSidebar.d.ts.map +1 -0
  183. package/dist/types/src/components/ChannelContainer.d.ts +14 -0
  184. package/dist/types/src/components/ChannelContainer.d.ts.map +1 -0
  185. package/dist/types/src/components/ChannelContainer.stories.d.ts +10 -0
  186. package/dist/types/src/components/ChannelContainer.stories.d.ts.map +1 -0
  187. package/dist/types/src/components/Chat.stories.d.ts.map +1 -1
  188. package/dist/types/src/components/ChatContainer.d.ts +9 -7
  189. package/dist/types/src/components/ChatContainer.d.ts.map +1 -1
  190. package/dist/types/src/components/CommentContainer.d.ts +11 -2
  191. package/dist/types/src/components/CommentContainer.d.ts.map +1 -1
  192. package/dist/types/src/components/Comments.stories.d.ts +1 -1
  193. package/dist/types/src/components/Comments.stories.d.ts.map +1 -1
  194. package/dist/types/src/components/CommentsContainer.d.ts +5 -9
  195. package/dist/types/src/components/CommentsContainer.d.ts.map +1 -1
  196. package/dist/types/src/components/Lobby/Lobby.d.ts +15 -0
  197. package/dist/types/src/components/Lobby/Lobby.d.ts.map +1 -0
  198. package/dist/types/src/components/Lobby/index.d.ts +2 -0
  199. package/dist/types/src/components/Lobby/index.d.ts.map +1 -0
  200. package/dist/types/src/components/Media/AudioStream.d.ts +6 -0
  201. package/dist/types/src/components/Media/AudioStream.d.ts.map +1 -0
  202. package/dist/types/src/components/Media/VideoObject.d.ts +15 -0
  203. package/dist/types/src/components/Media/VideoObject.d.ts.map +1 -0
  204. package/dist/types/src/components/Media/VideoObject.stories.d.ts +8 -0
  205. package/dist/types/src/components/Media/VideoObject.stories.d.ts.map +1 -0
  206. package/dist/types/src/components/Media/index.d.ts +3 -0
  207. package/dist/types/src/components/Media/index.d.ts.map +1 -0
  208. package/dist/types/src/components/MessageContainer.d.ts +5 -4
  209. package/dist/types/src/components/MessageContainer.d.ts.map +1 -1
  210. package/dist/types/src/components/Participant/Participant.d.ts +6 -0
  211. package/dist/types/src/components/Participant/Participant.d.ts.map +1 -0
  212. package/dist/types/src/components/Participant/ParticipantGrid.d.ts +11 -0
  213. package/dist/types/src/components/Participant/ParticipantGrid.d.ts.map +1 -0
  214. package/dist/types/src/components/Participant/index.d.ts +3 -0
  215. package/dist/types/src/components/Participant/index.d.ts.map +1 -0
  216. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.d.ts +12 -0
  217. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.d.ts.map +1 -0
  218. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts +10 -0
  219. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts.map +1 -0
  220. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.d.ts +32 -0
  221. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.d.ts.map +1 -0
  222. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts +23 -0
  223. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts.map +1 -0
  224. package/dist/types/src/components/ResponsiveGrid/ResponsiveGridItem.d.ts +21 -0
  225. package/dist/types/src/components/ResponsiveGrid/ResponsiveGridItem.d.ts.map +1 -0
  226. package/dist/types/src/components/ResponsiveGrid/index.d.ts +4 -0
  227. package/dist/types/src/components/ResponsiveGrid/index.d.ts.map +1 -0
  228. package/dist/types/src/components/ThreadComplementary.d.ts.map +1 -1
  229. package/dist/types/src/components/ThreadSettings.d.ts.map +1 -1
  230. package/dist/types/src/components/index.d.ts +5 -1
  231. package/dist/types/src/components/index.d.ts.map +1 -1
  232. package/dist/types/src/components/testing.d.ts +54 -119
  233. package/dist/types/src/components/testing.d.ts.map +1 -1
  234. package/dist/types/src/extensions/threads.d.ts.map +1 -1
  235. package/dist/types/src/hooks/analytics.d.ts +2 -2
  236. package/dist/types/src/hooks/analytics.d.ts.map +1 -1
  237. package/dist/types/src/hooks/index.d.ts +2 -1
  238. package/dist/types/src/hooks/index.d.ts.map +1 -1
  239. package/dist/types/src/hooks/useDebugMode.d.ts +2 -0
  240. package/dist/types/src/hooks/useDebugMode.d.ts.map +1 -0
  241. package/dist/types/src/hooks/useStatus.d.ts.map +1 -1
  242. package/dist/types/src/index.d.ts +1 -1
  243. package/dist/types/src/index.d.ts.map +1 -1
  244. package/dist/types/src/meta.d.ts.map +1 -1
  245. package/dist/types/src/peers.stories.d.ts +11 -0
  246. package/dist/types/src/peers.stories.d.ts.map +1 -0
  247. package/dist/types/src/testing/index.d.ts +2 -0
  248. package/dist/types/src/testing/index.d.ts.map +1 -0
  249. package/dist/types/src/testing/stories.d.ts +2 -0
  250. package/dist/types/src/testing/stories.d.ts.map +1 -0
  251. package/dist/types/src/translations.d.ts +35 -56
  252. package/dist/types/src/translations.d.ts.map +1 -1
  253. package/dist/types/src/types/index.d.ts +3 -0
  254. package/dist/types/src/types/index.d.ts.map +1 -0
  255. package/dist/types/src/types/schema.d.ts +317 -0
  256. package/dist/types/src/types/schema.d.ts.map +1 -0
  257. package/dist/types/src/types/types.d.ts +1015 -0
  258. package/dist/types/src/types/types.d.ts.map +1 -0
  259. package/dist/types/src/util.d.ts +2 -0
  260. package/dist/types/src/util.d.ts.map +1 -1
  261. package/dist/types/tsconfig.tsbuildinfo +1 -1
  262. package/package.json +60 -40
  263. package/src/ThreadPlugin.tsx +33 -14
  264. package/src/calls/call-manager.ts +242 -0
  265. package/src/calls/call-swarm-synchronizer.ts +350 -0
  266. package/src/calls/index.ts +10 -0
  267. package/src/calls/media-manager.ts +342 -0
  268. package/src/calls/speaking-monitor.ts +85 -0
  269. package/src/calls/types.ts +70 -0
  270. package/src/calls/util/audio.ts +58 -0
  271. package/src/calls/util/calls-service.ts +527 -0
  272. package/src/calls/util/history-cache.ts +27 -0
  273. package/src/calls/util/index.ts +8 -0
  274. package/src/calls/util/media.ts +52 -0
  275. package/src/calls/util/stub-media-streams.ts +73 -0
  276. package/src/calls/util/task-scheduling.ts +92 -0
  277. package/src/capabilities/app-graph-builder.ts +171 -25
  278. package/src/capabilities/call-manager.ts +19 -0
  279. package/src/capabilities/capabilities.ts +15 -1
  280. package/src/capabilities/index.ts +2 -0
  281. package/src/capabilities/intent-resolver.ts +76 -55
  282. package/src/capabilities/markdown.ts +54 -4
  283. package/src/capabilities/react-root.tsx +17 -0
  284. package/src/capabilities/react-surface.tsx +52 -27
  285. package/src/capabilities/state.ts +1 -1
  286. package/src/components/Call/Call.tsx +88 -0
  287. package/src/components/Call/Toolbar.tsx +182 -0
  288. package/src/components/Call/index.ts +6 -0
  289. package/src/components/CallDebugPanel.tsx +115 -0
  290. package/src/components/CallSidebar.tsx +17 -0
  291. package/src/components/ChannelContainer.stories.tsx +58 -0
  292. package/src/components/ChannelContainer.tsx +203 -0
  293. package/src/components/Chat.stories.tsx +9 -10
  294. package/src/components/ChatContainer.tsx +37 -25
  295. package/src/components/CommentContainer.tsx +56 -61
  296. package/src/components/Comments.stories.tsx +20 -16
  297. package/src/components/CommentsContainer.tsx +18 -28
  298. package/src/components/Lobby/Lobby.tsx +119 -0
  299. package/src/components/Lobby/index.ts +5 -0
  300. package/src/components/Media/AudioStream.tsx +67 -0
  301. package/src/components/Media/VideoObject.stories.tsx +52 -0
  302. package/src/components/Media/VideoObject.tsx +58 -0
  303. package/src/components/Media/index.ts +6 -0
  304. package/src/components/MessageContainer.tsx +31 -50
  305. package/src/components/Participant/Participant.tsx +57 -0
  306. package/src/components/Participant/ParticipantGrid.tsx +88 -0
  307. package/src/components/Participant/index.ts +6 -0
  308. package/src/components/ResponsiveGrid/ResponsiveContainer.stories.tsx +54 -0
  309. package/src/components/ResponsiveGrid/ResponsiveContainer.tsx +31 -0
  310. package/src/components/ResponsiveGrid/ResponsiveGrid.stories.tsx +156 -0
  311. package/src/components/ResponsiveGrid/ResponsiveGrid.tsx +341 -0
  312. package/src/components/ResponsiveGrid/ResponsiveGridItem.tsx +131 -0
  313. package/src/components/ResponsiveGrid/index.ts +7 -0
  314. package/src/components/ThreadComplementary.tsx +37 -42
  315. package/src/components/index.ts +4 -0
  316. package/src/components/testing.ts +4 -3
  317. package/src/extensions/threads.ts +42 -24
  318. package/src/hooks/analytics.ts +6 -2
  319. package/src/hooks/index.ts +2 -1
  320. package/src/hooks/useDebugMode.ts +25 -0
  321. package/src/index.ts +1 -1
  322. package/src/meta.ts +4 -3
  323. package/src/peers.stories.tsx +189 -0
  324. package/src/testing/index.ts +5 -0
  325. package/src/testing/stories.ts +50 -0
  326. package/src/translations.ts +46 -5
  327. package/src/types/index.ts +6 -0
  328. package/src/types/schema.ts +29 -0
  329. package/src/types/types.ts +110 -0
  330. package/src/typings/peermetrics-webrtc-stats.d.ts +30 -0
  331. package/src/util.ts +12 -0
  332. package/dist/lib/browser/ChatContainer-WC6KQDDU.mjs +0 -138
  333. package/dist/lib/browser/ChatContainer-WC6KQDDU.mjs.map +0 -7
  334. package/dist/lib/browser/app-graph-builder-6W4UKJDI.mjs +0 -41
  335. package/dist/lib/browser/app-graph-builder-6W4UKJDI.mjs.map +0 -7
  336. package/dist/lib/browser/chunk-AYNXYEKP.mjs.map +0 -7
  337. package/dist/lib/browser/chunk-EP6MRLY7.mjs.map +0 -7
  338. package/dist/lib/browser/chunk-FY5OCUP6.mjs +0 -207
  339. package/dist/lib/browser/chunk-FY5OCUP6.mjs.map +0 -7
  340. package/dist/lib/browser/chunk-Q66FBBJD.mjs +0 -17
  341. package/dist/lib/browser/chunk-Q66FBBJD.mjs.map +0 -7
  342. package/dist/lib/browser/chunk-WBJLUUOK.mjs.map +0 -7
  343. package/dist/lib/browser/chunk-WOG72DWE.mjs +0 -93
  344. package/dist/lib/browser/chunk-WOG72DWE.mjs.map +0 -7
  345. package/dist/lib/browser/intent-resolver-3UW6ROYT.mjs.map +0 -7
  346. package/dist/lib/browser/markdown-7KXBXCUS.mjs +0 -111
  347. package/dist/lib/browser/markdown-7KXBXCUS.mjs.map +0 -7
  348. package/dist/lib/browser/react-surface-F2AIYIUH.mjs +0 -437
  349. package/dist/lib/browser/react-surface-F2AIYIUH.mjs.map +0 -7
  350. package/dist/lib/browser/types.mjs +0 -10
  351. package/dist/lib/node/ChatContainer-LVYQ67PJ.cjs +0 -163
  352. package/dist/lib/node/ChatContainer-LVYQ67PJ.cjs.map +0 -7
  353. package/dist/lib/node/app-graph-builder-HZNWT4QU.cjs +0 -57
  354. package/dist/lib/node/app-graph-builder-HZNWT4QU.cjs.map +0 -7
  355. package/dist/lib/node/chunk-46BSFPBV.cjs +0 -113
  356. package/dist/lib/node/chunk-46BSFPBV.cjs.map +0 -7
  357. package/dist/lib/node/chunk-IX63EKGL.cjs.map +0 -7
  358. package/dist/lib/node/chunk-NQ5DTPOY.cjs.map +0 -7
  359. package/dist/lib/node/chunk-RIYLEDQ7.cjs +0 -232
  360. package/dist/lib/node/chunk-RIYLEDQ7.cjs.map +0 -7
  361. package/dist/lib/node/chunk-W25MBII2.cjs.map +0 -7
  362. package/dist/lib/node/intent-resolver-DC6HDNTX.cjs.map +0 -7
  363. package/dist/lib/node/markdown-L2WMCQKM.cjs +0 -121
  364. package/dist/lib/node/markdown-L2WMCQKM.cjs.map +0 -7
  365. package/dist/lib/node/react-surface-GP5IH5LN.cjs +0 -439
  366. package/dist/lib/node/react-surface-GP5IH5LN.cjs.map +0 -7
  367. package/dist/lib/node/types.cjs.map +0 -7
  368. package/dist/lib/node-esm/ChatContainer-WMOPMK5H.mjs +0 -139
  369. package/dist/lib/node-esm/ChatContainer-WMOPMK5H.mjs.map +0 -7
  370. package/dist/lib/node-esm/app-graph-builder-M3KK5QJH.mjs +0 -42
  371. package/dist/lib/node-esm/app-graph-builder-M3KK5QJH.mjs.map +0 -7
  372. package/dist/lib/node-esm/chunk-42F2DTMM.mjs.map +0 -7
  373. package/dist/lib/node-esm/chunk-7DOPZH6Y.mjs +0 -208
  374. package/dist/lib/node-esm/chunk-7DOPZH6Y.mjs.map +0 -7
  375. package/dist/lib/node-esm/chunk-E446MGLP.mjs +0 -94
  376. package/dist/lib/node-esm/chunk-E446MGLP.mjs.map +0 -7
  377. package/dist/lib/node-esm/chunk-QUTIMZJ4.mjs +0 -19
  378. package/dist/lib/node-esm/chunk-QUTIMZJ4.mjs.map +0 -7
  379. package/dist/lib/node-esm/chunk-T6E5EY7Z.mjs.map +0 -7
  380. package/dist/lib/node-esm/chunk-WLY2HMDB.mjs.map +0 -7
  381. package/dist/lib/node-esm/intent-resolver-OAMDKGAA.mjs.map +0 -7
  382. package/dist/lib/node-esm/markdown-ZKU23UVD.mjs +0 -112
  383. package/dist/lib/node-esm/markdown-ZKU23UVD.mjs.map +0 -7
  384. package/dist/lib/node-esm/react-surface-45GRKLWG.mjs +0 -438
  385. package/dist/lib/node-esm/react-surface-45GRKLWG.mjs.map +0 -7
  386. package/dist/lib/node-esm/types.mjs +0 -11
  387. package/dist/types/src/components/types.d.ts +0 -28
  388. package/dist/types/src/components/types.d.ts.map +0 -1
  389. package/dist/types/src/events.d.ts +0 -4
  390. package/dist/types/src/events.d.ts.map +0 -1
  391. package/dist/types/src/types.d.ts +0 -231
  392. package/dist/types/src/types.d.ts.map +0 -1
  393. package/src/components/types.ts +0 -32
  394. package/src/events.ts +0 -11
  395. package/src/types.ts +0 -100
  396. /package/dist/lib/browser/{types.mjs.map → ChannelContainer-LGYSQMC7.mjs.map} +0 -0
  397. /package/dist/lib/{node-esm/types.mjs.map → browser/ChatContainer-JWRI73OG.mjs.map} +0 -0
  398. /package/dist/lib/browser/{settings-2VZ7S4SK.mjs.map → settings-KVBQQSO5.mjs.map} +0 -0
  399. /package/dist/lib/node/{settings-7MGTJ46L.cjs.map → settings-H45P5YO2.cjs.map} +0 -0
  400. /package/dist/lib/node-esm/{settings-AJAZ3O47.mjs.map → settings-IJGUOU3F.mjs.map} +0 -0
@@ -0,0 +1,203 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Rx } from '@effect-rx/rx-react';
6
+ import React, { useCallback, useEffect, useMemo, useState, type ChangeEvent } from 'react';
7
+
8
+ import { useCapabilities, useCapability } from '@dxos/app-framework';
9
+ import { Context } from '@dxos/context';
10
+ import { log } from '@dxos/log';
11
+ import { useClient } from '@dxos/react-client';
12
+ import { fullyQualifiedId, getSpace } from '@dxos/react-client/echo';
13
+ import { useIdentity } from '@dxos/react-client/halo';
14
+ import { useTranslation, Input, ElevationProvider } from '@dxos/react-ui';
15
+ import { ControlGroup, ControlItemInput, ControlGroupButton } from '@dxos/react-ui-form';
16
+ import { ToolbarMenu, MenuProvider, createMenuAction, useMenuActions, createMenuItemGroup } from '@dxos/react-ui-menu';
17
+ import { useSoundEffect } from '@dxos/react-ui-sfx';
18
+ import { StackItem } from '@dxos/react-ui-stack';
19
+
20
+ import { Call } from './Call';
21
+ import ChatContainer from './ChatContainer';
22
+ import { ThreadCapabilities } from '../capabilities';
23
+ import { THREAD_PLUGIN } from '../meta';
24
+ import { type ChannelType } from '../types';
25
+
26
+ export type ChannelContainerProps = {
27
+ channel?: ChannelType;
28
+ roomId?: string;
29
+ role?: string;
30
+ fullscreen?: boolean;
31
+ };
32
+
33
+ /**
34
+ * Renders a call when active, otherwise renders the channel chat.
35
+ */
36
+ export const ChannelContainer = ({ channel, roomId: _roomId, role, fullscreen }: ChannelContainerProps) => {
37
+ const space = getSpace(channel);
38
+ const callManager = useCapability(ThreadCapabilities.CallManager);
39
+ const roomId = channel ? fullyQualifiedId(channel) : _roomId;
40
+ const identity = useIdentity();
41
+ const isNamed = !!identity?.profile?.displayName;
42
+ const joinSound = useSoundEffect('JoinCall');
43
+ const leaveSound = useSoundEffect('LeaveCall');
44
+
45
+ const extensions = useCapabilities(ThreadCapabilities.CallExtension);
46
+ useEffect(() => {
47
+ const ctx = new Context();
48
+ callManager.left.on(ctx, (roomId) => {
49
+ extensions.forEach((extension) => {
50
+ void extension.onLeave?.(roomId);
51
+ });
52
+ });
53
+
54
+ callManager.callStateUpdated.on(ctx, (state) => {
55
+ extensions.forEach((extension) => {
56
+ void extension.onCallStateUpdated?.(state);
57
+ });
58
+ });
59
+
60
+ callManager.mediaStateUpdated.on(ctx, (state) => {
61
+ extensions.forEach((extension) => {
62
+ void extension.onMediaStateUpdated?.(state);
63
+ });
64
+ });
65
+
66
+ return () => {
67
+ void ctx.dispose();
68
+ };
69
+ }, [callManager, extensions]);
70
+
71
+ /**
72
+ * Join the call.
73
+ */
74
+ // TODO(wittjosiah): Show preview before joining?
75
+ const handleJoin = useCallback(async () => {
76
+ if (!roomId || !channel) {
77
+ return;
78
+ }
79
+
80
+ if (callManager.joined) {
81
+ await callManager.leave();
82
+ }
83
+
84
+ try {
85
+ void joinSound.play();
86
+ callManager.setRoomId(roomId);
87
+ await callManager.join();
88
+ await Promise.all(extensions.map((extension) => extension.onJoin?.({ channel, roomId })));
89
+ } catch (err) {
90
+ // TODO(burdon): Error sound.
91
+ log.catch(err);
92
+ }
93
+ }, [extensions, channel, roomId]);
94
+
95
+ /**
96
+ * Leave the call.
97
+ */
98
+ const handleLeave = useCallback(async () => {
99
+ try {
100
+ void leaveSound.play();
101
+ } catch (err) {
102
+ // TODO(burdon): Error sound.
103
+ log.catch(err);
104
+ } finally {
105
+ void callManager.turnAudioOff();
106
+ void callManager.turnVideoOff();
107
+ void callManager.turnScreenshareOff();
108
+ void callManager.leave();
109
+ }
110
+ }, [extensions, roomId]);
111
+
112
+ const isJoined = callManager.joined && callManager.roomId === roomId;
113
+
114
+ return (
115
+ <StackItem.Content toolbar={!isJoined} classNames={isJoined && 'h-full'}>
116
+ {isJoined && !isNamed && <DisplayNameMissing />}
117
+ {isJoined && isNamed && (
118
+ <Call.Root>
119
+ <Call.Grid fullscreen={fullscreen} />
120
+ <Call.Toolbar channel={channel} onLeave={handleLeave} />
121
+ </Call.Root>
122
+ )}
123
+ {!isJoined && channel && channel.defaultThread.target && space && (
124
+ <>
125
+ <ChannelToolbar attendableId={fullyQualifiedId(channel)} role={role} onJoinCall={handleJoin} />
126
+ <ChatContainer space={space} thread={channel.defaultThread.target} />
127
+ </>
128
+ )}
129
+ </StackItem.Content>
130
+ );
131
+ };
132
+
133
+ export default ChannelContainer;
134
+
135
+ const DisplayNameMissing = () => {
136
+ const { t } = useTranslation(THREAD_PLUGIN);
137
+ const client = useClient();
138
+ const [displayName, setDisplayName] = useState('');
139
+ const handleChange = useCallback((event: ChangeEvent<HTMLInputElement>) => setDisplayName(event.target.value), []);
140
+ const handleSave = useCallback(() => client.halo.updateProfile({ displayName }), [client, displayName]);
141
+
142
+ return (
143
+ <ControlGroup classNames='p-4 place-content-center'>
144
+ <ControlItemInput title={t('display name label')} description={t('display name description')}>
145
+ <Input.TextInput
146
+ value={displayName}
147
+ onChange={handleChange}
148
+ placeholder={t('display name input placeholder')}
149
+ classNames='md:min-is-64'
150
+ />
151
+ </ControlItemInput>
152
+ <ControlGroupButton disabled={!displayName} onClick={handleSave}>
153
+ {t('set display name label')}
154
+ </ControlGroupButton>
155
+ </ControlGroup>
156
+ );
157
+ };
158
+
159
+ const useChannelToolbarActions = (onJoinCall?: () => void) => {
160
+ const creator = useMemo(
161
+ () =>
162
+ Rx.make(() => {
163
+ const nodes = [];
164
+ const edges = [];
165
+
166
+ const rootGroup = createMenuItemGroup('root', {
167
+ label: ['channel toolbar title', { ns: THREAD_PLUGIN }],
168
+ });
169
+ nodes.push(rootGroup);
170
+
171
+ const sortAction = createMenuAction('video-call', () => onJoinCall?.(), {
172
+ label: ['start video call label', { ns: THREAD_PLUGIN }],
173
+ icon: 'ph--video-camera--regular',
174
+ type: 'video-call',
175
+ });
176
+ nodes.push(sortAction);
177
+ edges.push({ source: 'root', target: sortAction.id });
178
+
179
+ return { nodes, edges };
180
+ }),
181
+ [],
182
+ );
183
+
184
+ return useMenuActions(creator);
185
+ };
186
+
187
+ type ChannelToolbarProps = {
188
+ attendableId?: string;
189
+ role?: string;
190
+ onJoinCall?: () => void;
191
+ };
192
+
193
+ const ChannelToolbar = ({ attendableId, role, onJoinCall }: ChannelToolbarProps) => {
194
+ const menuProps = useChannelToolbarActions(onJoinCall);
195
+
196
+ return (
197
+ <ElevationProvider elevation={role === 'section' ? 'positioned' : 'base'}>
198
+ <MenuProvider {...menuProps} attendableId={attendableId}>
199
+ <ToolbarMenu />
200
+ </MenuProvider>
201
+ </ElevationProvider>
202
+ );
203
+ };
@@ -9,21 +9,19 @@ import React, { useEffect, useState } from 'react';
9
9
 
10
10
  import { Capabilities, contributes, createSurface, IntentPlugin } from '@dxos/app-framework';
11
11
  import { withPluginManager } from '@dxos/app-framework/testing';
12
- import { ObjectId } from '@dxos/echo-schema';
13
- import { DXN, QueueSubspaceTags } from '@dxos/keys';
14
- import { refFromDXN } from '@dxos/live-object';
15
- import { ChannelType, ThreadType } from '@dxos/plugin-space/types';
12
+ import { makeRef } from '@dxos/live-object';
16
13
  import { faker } from '@dxos/random';
17
14
  import { useClient } from '@dxos/react-client';
18
15
  import { live, type Space } from '@dxos/react-client/echo';
19
16
  import { useIdentity } from '@dxos/react-client/halo';
20
17
  import { withClientProvider } from '@dxos/react-client/testing';
21
18
  import { Thread } from '@dxos/react-ui-thread';
22
- import { MessageType } from '@dxos/schema';
19
+ import { DataType } from '@dxos/schema';
23
20
  import { withLayout, withTheme } from '@dxos/storybook-utils';
24
21
 
25
22
  import { ChatContainer } from './ChatContainer';
26
23
  import translations from '../translations';
24
+ import { ChannelType, ThreadType } from '../types';
27
25
 
28
26
  faker.seed(1);
29
27
 
@@ -39,7 +37,8 @@ const Story = () => {
39
37
  const space = await client.spaces.create();
40
38
  const channel = space.db.add(
41
39
  live(ChannelType, {
42
- queue: refFromDXN(new DXN(DXN.kind.QUEUE, [QueueSubspaceTags.DATA, space.id, ObjectId.random()])),
40
+ defaultThread: makeRef(live(ThreadType, { messages: [], status: 'active' })),
41
+ threads: [],
43
42
  }),
44
43
  );
45
44
  setSpace(space);
@@ -48,13 +47,13 @@ const Story = () => {
48
47
  }
49
48
  }, [identity]);
50
49
 
51
- if (!identity || !channel || !space) {
50
+ if (!identity || !channel || !space || !channel.defaultThread.target) {
52
51
  return null;
53
52
  }
54
53
 
55
54
  return (
56
55
  <main className='max-is-prose mli-auto bs-dvh overflow-hidden'>
57
- <ChatContainer space={space} dxn={channel.queue.dxn} />
56
+ <ChatContainer space={space} thread={channel.defaultThread.target} />
58
57
  </main>
59
58
  );
60
59
  };
@@ -80,8 +79,8 @@ const meta: Meta = {
80
79
  ],
81
80
  }),
82
81
  withTheme,
83
- withLayout({ fullscreen: true, tooltips: true }),
84
- withClientProvider({ createSpace: true, types: [ThreadType, MessageType] }),
82
+ withLayout({ fullscreen: true }),
83
+ withClientProvider({ createSpace: true, types: [ThreadType, DataType.Message] }),
85
84
  ],
86
85
  parameters: { translations },
87
86
  };
@@ -4,23 +4,29 @@
4
4
 
5
5
  import React, { useLayoutEffect, useMemo, useRef, useState } from 'react';
6
6
 
7
- import { create } from '@dxos/echo-schema';
8
- import { type DXN } from '@dxos/keys';
9
- import { makeRef } from '@dxos/live-object';
10
- import { type Space, useMembers, useQueue } from '@dxos/react-client/echo';
7
+ import { live, makeRef } from '@dxos/live-object';
8
+ import { type AnyLiveObject, fullyQualifiedId, type Space, useMembers } from '@dxos/react-client/echo';
11
9
  import { useIdentity } from '@dxos/react-client/halo';
12
10
  import { Icon, ScrollArea, useThemeContext, useTranslation } from '@dxos/react-ui';
13
11
  import { createBasicExtensions, createThemeExtensions, listener } from '@dxos/react-ui-editor';
14
12
  import { StackItem } from '@dxos/react-ui-stack';
15
13
  import { mx } from '@dxos/react-ui-theme';
16
- import { MessageTextbox, type MessageTextboxProps, Thread, ThreadFooter, threadLayout } from '@dxos/react-ui-thread';
17
- import { MessageType } from '@dxos/schema';
14
+ import {
15
+ MessageTextbox,
16
+ type MessageTextboxProps,
17
+ Thread,
18
+ ThreadFooter,
19
+ threadLayout,
20
+ type ThreadProps,
21
+ } from '@dxos/react-ui-thread';
22
+ import { DataType } from '@dxos/schema';
23
+ import { isNonNullable } from '@dxos/util';
18
24
 
19
25
  import { MessageContainer } from './MessageContainer';
20
26
  import { command } from './command-extension';
21
- import { type ThreadContainerProps } from './types';
22
27
  import { useStatus } from '../hooks';
23
28
  import { THREAD_PLUGIN } from '../meta';
29
+ import { type ThreadType } from '../types';
24
30
  import { getMessageMetadata } from '../util';
25
31
 
26
32
  export const ChatHeading = ({ attendableId }: { attendableId?: string }) => {
@@ -35,16 +41,17 @@ export const ChatHeading = ({ attendableId }: { attendableId?: string }) => {
35
41
  );
36
42
  };
37
43
 
38
- export type ChatContainerProps = Omit<ThreadContainerProps, 'thread'> & {
44
+ export type ChatContainerProps = {
39
45
  space: Space;
40
- dxn: DXN;
41
- };
46
+ thread: ThreadType;
47
+ context?: AnyLiveObject<any>;
48
+ autoFocusTextbox?: boolean;
49
+ } & Pick<ThreadProps, 'current'>;
42
50
 
43
- export const ChatContainer = ({ space, dxn, context, current, autoFocusTextbox }: ChatContainerProps) => {
44
- const id = dxn.toString();
51
+ export const ChatContainer = ({ space, thread, context, current, autoFocusTextbox }: ChatContainerProps) => {
52
+ const id = fullyQualifiedId(thread);
45
53
  const identity = useIdentity()!;
46
54
  const members = useMembers(space?.key);
47
- const queue = useQueue<MessageType>(dxn, { pollInterval: 1_000 });
48
55
  const activity = useStatus(space, id);
49
56
  const { t } = useTranslation(THREAD_PLUGIN);
50
57
  // TODO(wittjosiah): This is a hack to reset the editor after a message is sent.
@@ -79,18 +86,20 @@ export const ChatContainer = ({ space, dxn, context, current, autoFocusTextbox }
79
86
 
80
87
  // TODO(burdon): Change to model.
81
88
  const handleCreate: MessageTextboxProps['onSend'] = () => {
82
- if (!messageRef.current?.length || !queue) {
89
+ if (!messageRef.current?.length) {
83
90
  return false;
84
91
  }
85
92
 
86
- queue.append([
87
- create(MessageType, {
88
- sender: { identityDid: identity.did },
89
- created: new Date().toISOString(),
90
- blocks: [{ type: 'text', text: messageRef.current }],
91
- properties: context ? { context: makeRef(context) } : undefined,
92
- }),
93
- ]);
93
+ thread.messages.push(
94
+ makeRef(
95
+ live(DataType.Message, {
96
+ sender: { identityDid: identity.did },
97
+ created: new Date().toISOString(),
98
+ blocks: [{ type: 'text', text: messageRef.current }],
99
+ properties: context ? { context: makeRef(context) } : undefined,
100
+ }),
101
+ ),
102
+ );
94
103
 
95
104
  messageRef.current = '';
96
105
  setAutoFocus(true);
@@ -108,9 +117,12 @@ export const ChatContainer = ({ space, dxn, context, current, autoFocusTextbox }
108
117
  <ScrollArea.Root classNames='col-span-2'>
109
118
  <ScrollArea.Viewport classNames='overflow-anchored after:overflow-anchor after:block after:bs-px after:-mbs-px [&>div]:min-bs-full [&>div]:!grid [&>div]:grid-rows-[1fr_0]'>
110
119
  <div role='none' className={mx(threadLayout, 'place-self-end')}>
111
- {(queue?.items ?? []).map((message) => (
112
- <MessageContainer key={message.id} message={message} members={members} />
113
- ))}
120
+ {thread.messages
121
+ .map((message) => message.target)
122
+ .filter(isNonNullable)
123
+ .map((message) => (
124
+ <MessageContainer key={message.id} message={message} members={members} />
125
+ ))}
114
126
  </div>
115
127
  {/* NOTE(thure): This can’t also be the `overflow-anchor` because `ScrollArea` injects an interceding node that contains this necessary ref’d element. */}
116
128
  <div role='none' className='bs-px -mbs-px' ref={threadScrollRef} />
@@ -5,6 +5,7 @@
5
5
  import { CheckCircle, X } from '@phosphor-icons/react';
6
6
  import React, { useCallback, useMemo, useRef, useState } from 'react';
7
7
 
8
+ import { RelationSourceId } from '@dxos/echo-schema';
8
9
  import { RefArray } from '@dxos/live-object';
9
10
  import { fullyQualifiedId, getSpace, useMembers } from '@dxos/react-client/echo';
10
11
  import { useIdentity } from '@dxos/react-client/halo';
@@ -17,14 +18,22 @@ import {
17
18
  hoverableFocusedWithinControls,
18
19
  mx,
19
20
  } from '@dxos/react-ui-theme';
20
- import { MessageTextbox, type MessageTextboxProps, Thread, ThreadFooter, ThreadHeading } from '@dxos/react-ui-thread';
21
+ import {
22
+ MessageTextbox,
23
+ type MessageTextboxProps,
24
+ Thread,
25
+ ThreadFooter,
26
+ ThreadHeading,
27
+ type ThreadProps,
28
+ } from '@dxos/react-ui-thread';
29
+ import { type AnchoredTo } from '@dxos/schema';
21
30
  import { isNonNullable } from '@dxos/util';
22
31
 
23
32
  import { MessageContainer } from './MessageContainer';
24
33
  import { command } from './command-extension';
25
- import { type ThreadContainerProps } from './types';
26
34
  import { useStatus } from '../hooks';
27
35
  import { THREAD_PLUGIN } from '../meta';
36
+ import { type ThreadType } from '../types';
28
37
  import { getMessageMetadata } from '../util';
29
38
 
30
39
  const sizeClass = getSize(4);
@@ -42,25 +51,17 @@ const ToggleResolvedButton = ({
42
51
  const { t } = useTranslation(THREAD_PLUGIN);
43
52
  const label = t(isResolved ? 'mark as unresolved label' : 'mark as resolved label');
44
53
  return (
45
- <Tooltip.Root>
46
- <Tooltip.Trigger asChild>
47
- <Button
48
- variant='ghost'
49
- data-testid='thread.toggle-resolved'
50
- onClick={onResolve}
51
- classNames={[commentControlClassNames, !isResolved && hoverableControlItem]}
52
- >
53
- <span className='sr-only'>{label}</span>
54
- {isResolved ? <CheckCircle className={sizeClass} weight='fill' /> : <CheckCircle className={sizeClass} />}
55
- </Button>
56
- </Tooltip.Trigger>
57
- <Tooltip.Portal>
58
- <Tooltip.Content>
59
- {label}
60
- <Tooltip.Arrow />
61
- </Tooltip.Content>
62
- </Tooltip.Portal>
63
- </Tooltip.Root>
54
+ <Tooltip.Trigger asChild content={label}>
55
+ <Button
56
+ variant='ghost'
57
+ data-testid='thread.toggle-resolved'
58
+ onClick={onResolve}
59
+ classNames={[commentControlClassNames, !isResolved && hoverableControlItem]}
60
+ >
61
+ <span className='sr-only'>{label}</span>
62
+ {isResolved ? <CheckCircle className={sizeClass} weight='fill' /> : <CheckCircle className={sizeClass} />}
63
+ </Button>
64
+ </Tooltip.Trigger>
64
65
  );
65
66
  };
66
67
 
@@ -68,41 +69,43 @@ const DeleteThreadButton = ({ onDelete }: { onDelete: () => void }) => {
68
69
  const { t } = useTranslation(THREAD_PLUGIN);
69
70
  const label = t('delete thread label');
70
71
  return (
71
- <Tooltip.Root>
72
- <Tooltip.Trigger asChild>
73
- <Button
74
- variant='ghost'
75
- data-testid='thread.delete'
76
- onClick={onDelete}
77
- classNames={[commentControlClassNames, hoverableControlItem]}
78
- >
79
- <span className='sr-only'>{label}</span>
80
- <X className={sizeClass} />
81
- </Button>
82
- </Tooltip.Trigger>
83
- <Tooltip.Portal>
84
- <Tooltip.Content classNames='z-30'>
85
- {label}
86
- <Tooltip.Arrow />
87
- </Tooltip.Content>
88
- </Tooltip.Portal>
89
- </Tooltip.Root>
72
+ <Tooltip.Trigger asChild content={label}>
73
+ <Button
74
+ variant='ghost'
75
+ data-testid='thread.delete'
76
+ onClick={onDelete}
77
+ classNames={[commentControlClassNames, hoverableControlItem]}
78
+ >
79
+ <span className='sr-only'>{label}</span>
80
+ <X className={sizeClass} />
81
+ </Button>
82
+ </Tooltip.Trigger>
90
83
  );
91
84
  };
92
85
 
86
+ export type CommentContainerProps = {
87
+ anchor: AnchoredTo;
88
+ onAttend?: (anchor: AnchoredTo) => void;
89
+ onComment?: (anchor: AnchoredTo, message: string) => void;
90
+ onResolve?: (anchor: AnchoredTo) => void;
91
+ onMessageDelete?: (anchor: AnchoredTo, messageId: string) => void;
92
+ onThreadDelete?: (anchor: AnchoredTo) => void;
93
+ } & Pick<ThreadProps, 'current'>;
94
+
93
95
  export const CommentContainer = ({
94
- thread,
95
- detached,
96
+ anchor,
96
97
  current,
97
98
  onAttend,
98
99
  onComment,
99
100
  onResolve,
100
101
  onMessageDelete,
101
102
  onThreadDelete,
102
- }: ThreadContainerProps) => {
103
+ }: CommentContainerProps) => {
103
104
  const identity = useIdentity()!;
104
- const space = getSpace(thread);
105
+ const space = getSpace(anchor);
105
106
  const members = useMembers(space?.key);
107
+ const detached = !anchor.anchor;
108
+ const thread = anchor[RelationSourceId] as ThreadType;
106
109
  const activity = useStatus(space, fullyQualifiedId(thread));
107
110
  const { t } = useTranslation(THREAD_PLUGIN);
108
111
  const threadScrollRef = useRef<HTMLDivElement | null>(null);
@@ -127,23 +130,23 @@ export const CommentContainer = ({
127
130
  const scrollToEnd = (behavior: ScrollBehavior) =>
128
131
  setTimeout(() => threadScrollRef.current?.scrollIntoView({ behavior, block: 'end' }), 10);
129
132
 
130
- const handleAttend = useCallback(() => onAttend?.(thread), [onAttend, thread]);
131
- const handleResolve = useCallback(() => onResolve?.(thread), [onResolve, thread]);
132
- const handleMessageDelete = useCallback((id: string) => onMessageDelete?.(thread, id), [onMessageDelete, thread]);
133
- const handleThreadDelete = useCallback(() => onThreadDelete?.(thread), [onThreadDelete, thread]);
133
+ const handleAttend = useCallback(() => onAttend?.(anchor), [onAttend, anchor]);
134
+ const handleResolve = useCallback(() => onResolve?.(anchor), [onResolve, anchor]);
135
+ const handleMessageDelete = useCallback((id: string) => onMessageDelete?.(anchor, id), [onMessageDelete, anchor]);
136
+ const handleThreadDelete = useCallback(() => onThreadDelete?.(anchor), [onThreadDelete, anchor]);
134
137
 
135
138
  const handleComment: MessageTextboxProps['onSend'] = useCallback(() => {
136
139
  if (!messageRef.current) {
137
140
  return false;
138
141
  }
139
142
 
140
- onComment?.(thread, messageRef.current);
143
+ onComment?.(anchor, messageRef.current);
141
144
  messageRef.current = '';
142
145
  scrollToEnd('instant');
143
146
  rerenderEditor();
144
147
 
145
148
  return true;
146
- }, [thread, identity]);
149
+ }, [anchor, identity]);
147
150
 
148
151
  return (
149
152
  <Thread onClickCapture={handleAttend} onFocusCapture={handleAttend} current={current} id={fullyQualifiedId(thread)}>
@@ -156,17 +159,9 @@ export const CommentContainer = ({
156
159
  )}
157
160
  >
158
161
  {detached ? (
159
- <Tooltip.Root>
160
- <Tooltip.Trigger asChild>
161
- <ThreadHeading detached>{thread.name}</ThreadHeading>
162
- </Tooltip.Trigger>
163
- <Tooltip.Portal>
164
- <Tooltip.Content classNames='z-30' side='top'>
165
- {t('detached thread label')}
166
- <Tooltip.Arrow />
167
- </Tooltip.Content>
168
- </Tooltip.Portal>
169
- </Tooltip.Root>
162
+ <Tooltip.Trigger asChild content={t('detached thread label')} side='top'>
163
+ <ThreadHeading detached>{thread.name}</ThreadHeading>
164
+ </Tooltip.Trigger>
170
165
  ) : (
171
166
  <ThreadHeading>{thread.name}</ThreadHeading>
172
167
  )}
@@ -5,67 +5,71 @@
5
5
  import '@dxos-theme';
6
6
 
7
7
  import { type Meta } from '@storybook/react';
8
- import React, { useEffect, useState } from 'react';
8
+ import React, { useEffect } from 'react';
9
9
 
10
10
  import { IntentPlugin } from '@dxos/app-framework';
11
11
  import { withPluginManager } from '@dxos/app-framework/testing';
12
- import { ThreadType } from '@dxos/plugin-space/types';
12
+ import { Expando, Query, RelationSourceId, RelationTargetId } from '@dxos/echo-schema';
13
13
  import { faker } from '@dxos/random';
14
- import { Filter, fullyQualifiedId, useQuery, useSpace } from '@dxos/react-client/echo';
14
+ import { live, useQuery, useSpace } from '@dxos/react-client/echo';
15
15
  import { useIdentity } from '@dxos/react-client/halo';
16
16
  import { type ClientRepeatedComponentProps, ClientRepeater } from '@dxos/react-client/testing';
17
- import { MessageType } from '@dxos/schema';
17
+ import { AnchoredTo, DataType } from '@dxos/schema';
18
18
  import { withLayout, withTheme } from '@dxos/storybook-utils';
19
19
 
20
20
  import { CommentsContainer } from './CommentsContainer';
21
21
  import { createCommentThread } from './testing';
22
22
  import translations from '../translations';
23
+ import { ThreadType } from '../types';
23
24
 
24
25
  faker.seed(1);
25
26
 
26
27
  const Story = ({ spaceKey }: ClientRepeatedComponentProps) => {
27
28
  const identity = useIdentity();
28
29
  const space = useSpace(spaceKey);
29
- const threads = useQuery(space, Filter.schema(ThreadType));
30
- const [detached, setDetached] = useState<string[]>([]);
30
+ const anchors = useQuery(space, Query.type(AnchoredTo));
31
31
 
32
32
  useEffect(() => {
33
33
  if (identity && space) {
34
34
  const t = setTimeout(async () => {
35
- space.db.add(createCommentThread(identity));
36
- const thread = space.db.add(createCommentThread(identity));
37
- setDetached([fullyQualifiedId(thread)]);
35
+ const object = space.db.add(live(Expando, {}));
36
+ const thread1 = space.db.add(createCommentThread(identity));
37
+ const thread2 = space.db.add(createCommentThread(identity));
38
+ space.db.add(live(AnchoredTo, { [RelationSourceId]: thread1, [RelationTargetId]: object }));
39
+ space.db.add(live(AnchoredTo, { [RelationSourceId]: thread2, [RelationTargetId]: object }));
38
40
  });
39
41
 
40
42
  return () => clearTimeout(t);
41
43
  }
42
44
  }, [identity, space]);
43
45
 
44
- if (!identity || !space || !threads) {
46
+ if (!identity || !space || !anchors) {
45
47
  return null;
46
48
  }
47
49
 
48
50
  return (
49
51
  <div className='flex justify-center overflow-y-auto bg-white dark:bg-black'>
50
52
  <div className='flex flex-col w-[30rem]'>
51
- <CommentsContainer threads={threads} detached={detached} onThreadDelete={console.log} />
53
+ <CommentsContainer anchors={anchors} onThreadDelete={console.log} />
52
54
  </div>
53
55
  </div>
54
56
  );
55
57
  };
56
58
 
57
- export const Default = {};
58
-
59
59
  const meta: Meta = {
60
60
  title: 'plugins/plugin-thread/Comments',
61
61
  // TODO(wittjosiah): Use decorator.
62
- render: () => <ClientRepeater component={Story} createIdentity createSpace types={[ThreadType, MessageType]} />,
62
+ render: () => <ClientRepeater component={Story} createIdentity createSpace types={[ThreadType, DataType.Message]} />,
63
63
  decorators: [
64
64
  withTheme,
65
- withLayout({ fullscreen: true, tooltips: true }),
66
- withPluginManager({ plugins: [IntentPlugin()] }),
65
+ withLayout({ fullscreen: true }),
66
+ withPluginManager({
67
+ plugins: [IntentPlugin()],
68
+ }),
67
69
  ],
68
70
  parameters: { translations },
69
71
  };
70
72
 
71
73
  export default meta;
74
+
75
+ export const Default = {};