@dxos/plugin-thread 0.8.1-staging.9eaf14f → 0.8.2-main.10c050d

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-XFNGSLHL.mjs +15 -0
  2. package/dist/lib/browser/ChatContainer-JWRI73OG.mjs +14 -0
  3. package/dist/lib/browser/app-graph-builder-K3CFBN7V.mjs +171 -0
  4. package/dist/lib/browser/app-graph-builder-K3CFBN7V.mjs.map +7 -0
  5. package/dist/lib/browser/call-manager-I4IKVCAK.mjs +23 -0
  6. package/dist/lib/browser/call-manager-I4IKVCAK.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-QDJ3Y6WF.mjs → chunk-5P5BH5GE.mjs} +57 -35
  8. package/dist/lib/browser/chunk-5P5BH5GE.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-5PGLGDIP.mjs +983 -0
  10. package/dist/lib/browser/chunk-5PGLGDIP.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-G3TS64FP.mjs +351 -0
  12. package/dist/lib/browser/chunk-G3TS64FP.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-WBJLUUOK.mjs → chunk-IIUTBDVB.mjs} +4 -4
  14. package/dist/lib/browser/chunk-IIUTBDVB.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-IYY42OE2.mjs +545 -0
  16. package/dist/lib/browser/chunk-IYY42OE2.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-JKQUJOTX.mjs +31 -0
  18. package/dist/lib/browser/chunk-JKQUJOTX.mjs.map +7 -0
  19. package/dist/lib/browser/chunk-N2V6MV6B.mjs +21 -0
  20. package/dist/lib/browser/chunk-N2V6MV6B.mjs.map +7 -0
  21. package/dist/lib/browser/{chunk-EP6MRLY7.mjs → chunk-R5MDLUPC.mjs} +5 -3
  22. package/dist/lib/browser/chunk-R5MDLUPC.mjs.map +7 -0
  23. package/dist/lib/browser/chunk-RJGJXXWK.mjs +1708 -0
  24. package/dist/lib/browser/chunk-RJGJXXWK.mjs.map +7 -0
  25. package/dist/lib/browser/chunk-WDOQXTI2.mjs +126 -0
  26. package/dist/lib/browser/chunk-WDOQXTI2.mjs.map +7 -0
  27. package/dist/lib/browser/index.mjs +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-YYDCVHGL.mjs +27 -0
  35. package/dist/lib/browser/react-root-YYDCVHGL.mjs.map +7 -0
  36. package/dist/lib/browser/react-surface-MEYBFPBC.mjs +108 -0
  37. package/dist/lib/browser/react-surface-MEYBFPBC.mjs.map +7 -0
  38. package/dist/lib/browser/{settings-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-F24RHJPX.cjs +36 -0
  45. package/dist/lib/node/ChannelContainer-F24RHJPX.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-FZ4OMTB6.cjs +37 -0
  51. package/dist/lib/node/call-manager-FZ4OMTB6.cjs.map +7 -0
  52. package/dist/lib/node/chunk-4B3PPXA6.cjs +371 -0
  53. package/dist/lib/node/chunk-4B3PPXA6.cjs.map +7 -0
  54. package/dist/lib/node/{chunk-NQ5DTPOY.cjs → chunk-4YSNVPWU.cjs} +10 -8
  55. package/dist/lib/node/chunk-4YSNVPWU.cjs.map +7 -0
  56. package/dist/lib/node/chunk-6B3M6XRE.cjs +984 -0
  57. package/dist/lib/node/chunk-6B3M6XRE.cjs.map +7 -0
  58. package/dist/lib/node/chunk-AUIU6JGD.cjs +549 -0
  59. package/dist/lib/node/chunk-AUIU6JGD.cjs.map +7 -0
  60. package/dist/lib/node/chunk-ECIVLX56.cjs +1731 -0
  61. package/dist/lib/node/chunk-ECIVLX56.cjs.map +7 -0
  62. package/dist/lib/node/{chunk-S2A6BXEA.cjs → chunk-EYAUPLHT.cjs} +16 -10
  63. package/dist/lib/node/chunk-EYAUPLHT.cjs.map +7 -0
  64. package/dist/lib/node/{chunk-AKINTFBH.cjs → chunk-FUXJAVFZ.cjs} +50 -29
  65. package/dist/lib/node/chunk-FUXJAVFZ.cjs.map +7 -0
  66. package/dist/lib/node/{chunk-ONLWOUYZ.cjs → chunk-HLMCEE5K.cjs} +7 -7
  67. package/dist/lib/node/{chunk-ONLWOUYZ.cjs.map → chunk-HLMCEE5K.cjs.map} +2 -2
  68. package/dist/lib/node/chunk-LR5NENBE.cjs +54 -0
  69. package/dist/lib/node/chunk-LR5NENBE.cjs.map +7 -0
  70. package/dist/lib/node/chunk-TKHJVC2C.cjs +147 -0
  71. package/dist/lib/node/chunk-TKHJVC2C.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-HQDBRGD3.cjs +51 -0
  80. package/dist/lib/node/react-root-HQDBRGD3.cjs.map +7 -0
  81. package/dist/lib/node/react-surface-KY5KFKVQ.cjs +122 -0
  82. package/dist/lib/node/react-surface-KY5KFKVQ.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-AOXWXM53.mjs +16 -0
  90. package/dist/lib/node-esm/ChannelContainer-AOXWXM53.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-B3D3RK3R.mjs +24 -0
  96. package/dist/lib/node-esm/call-manager-B3D3RK3R.mjs.map +7 -0
  97. package/dist/lib/node-esm/chunk-CSO73XLB.mjs +546 -0
  98. package/dist/lib/node-esm/chunk-CSO73XLB.mjs.map +7 -0
  99. package/dist/lib/node-esm/{chunk-42F2DTMM.mjs → chunk-ESQC6SYE.mjs} +4 -4
  100. package/dist/lib/node-esm/chunk-ESQC6SYE.mjs.map +7 -0
  101. package/dist/lib/node-esm/chunk-J323VQ4P.mjs +127 -0
  102. package/dist/lib/node-esm/chunk-J323VQ4P.mjs.map +7 -0
  103. package/dist/lib/node-esm/chunk-JJLYSLLU.mjs +23 -0
  104. package/dist/lib/node-esm/chunk-JJLYSLLU.mjs.map +7 -0
  105. package/dist/lib/node-esm/{chunk-WLY2HMDB.mjs → chunk-K4KAUOKT.mjs} +5 -3
  106. package/dist/lib/node-esm/chunk-K4KAUOKT.mjs.map +7 -0
  107. package/dist/lib/node-esm/{chunk-J56FORYF.mjs → chunk-O3V45YJP.mjs} +57 -35
  108. package/dist/lib/node-esm/chunk-O3V45YJP.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-WBNC7KMA.mjs +1710 -0
  114. package/dist/lib/node-esm/chunk-WBNC7KMA.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-MKN5SK3G.mjs +28 -0
  125. package/dist/lib/node-esm/react-root-MKN5SK3G.mjs.map +7 -0
  126. package/dist/lib/node-esm/react-surface-J2C7CVX7.mjs +109 -0
  127. package/dist/lib/node-esm/react-surface-J2C7CVX7.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-XFNGSLHL.mjs.map} +0 -0
  407. /package/dist/lib/{node-esm/types.mjs.map → browser/ChatContainer-JWRI73OG.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
- import { create, type Space } from '@dxos/react-client/echo';
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
 
@@ -38,8 +36,9 @@ const Story = () => {
38
36
  setTimeout(async () => {
39
37
  const space = await client.spaces.create();
40
38
  const channel = space.db.add(
41
- create(ChannelType, {
42
- queue: refFromDXN(new DXN(DXN.kind.QUEUE, [QueueSubspaceTags.DATA, space.id, ObjectId.random()])),
39
+ live(ChannelType, {
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 { createStatic } 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
- createStatic(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 = {};