@dxos/plugin-thread 0.8.4-main.abd8ff62ef → 0.8.4-main.bc2380dfbc

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 (431) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +1 -1
  3. package/dist/lib/neutral/ChannelArticle-ACZD7YFT.mjs +28 -0
  4. package/dist/lib/neutral/ChannelArticle-ACZD7YFT.mjs.map +7 -0
  5. package/dist/lib/neutral/ChannelChat-6YTD5HWL.mjs +10 -0
  6. package/dist/lib/neutral/ThreadCompanion-NQWPS2H6.mjs +208 -0
  7. package/dist/lib/neutral/ThreadCompanion-NQWPS2H6.mjs.map +7 -0
  8. package/dist/lib/neutral/ThreadContainer-XYEPEOSD.mjs +61 -0
  9. package/dist/lib/neutral/ThreadContainer-XYEPEOSD.mjs.map +7 -0
  10. package/dist/lib/neutral/ThreadPlugin.mjs +80 -0
  11. package/dist/lib/neutral/ThreadPlugin.mjs.map +7 -0
  12. package/dist/lib/neutral/ThreadPlugin.node.mjs +40 -0
  13. package/dist/lib/neutral/ThreadPlugin.node.mjs.map +7 -0
  14. package/dist/lib/neutral/ThreadPlugin.workerd.mjs +24 -0
  15. package/dist/lib/neutral/ThreadPlugin.workerd.mjs.map +7 -0
  16. package/dist/lib/neutral/ThreadSettings-5MKTDK3A.mjs +15 -0
  17. package/dist/lib/neutral/ThreadSettings-5MKTDK3A.mjs.map +7 -0
  18. package/dist/lib/{browser/add-message-LRVGIHDH.mjs → neutral/add-message-FBIROBEZ.mjs} +8 -10
  19. package/dist/lib/neutral/add-message-FBIROBEZ.mjs.map +7 -0
  20. package/dist/lib/neutral/app-graph-builder-7Q6MA6RT.mjs +120 -0
  21. package/dist/lib/neutral/app-graph-builder-7Q6MA6RT.mjs.map +7 -0
  22. package/dist/lib/{browser/append-channel-message-CO3M6FSA.mjs → neutral/append-channel-message-FTFAD3PK.mjs} +5 -5
  23. package/dist/lib/neutral/append-channel-message-FTFAD3PK.mjs.map +7 -0
  24. package/dist/lib/neutral/blueprint-definition-S3EBOH4R.mjs +15 -0
  25. package/dist/lib/neutral/blueprint-definition-S3EBOH4R.mjs.map +7 -0
  26. package/dist/lib/neutral/blueprints/index.mjs +8 -0
  27. package/dist/lib/neutral/capabilities/index.mjs +25 -0
  28. package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
  29. package/dist/lib/{browser/blueprints/index.mjs → neutral/chunk-5T5LPLBN.mjs} +4 -5
  30. package/dist/lib/neutral/chunk-5T5LPLBN.mjs.map +7 -0
  31. package/dist/lib/neutral/chunk-7GHUS3IX.mjs +20 -0
  32. package/dist/lib/neutral/chunk-7GHUS3IX.mjs.map +7 -0
  33. package/dist/lib/neutral/chunk-D5LGFCUY.mjs +55 -0
  34. package/dist/lib/neutral/chunk-D5LGFCUY.mjs.map +7 -0
  35. package/dist/lib/neutral/chunk-JLY4NVTA.mjs +38 -0
  36. package/dist/lib/neutral/chunk-JLY4NVTA.mjs.map +7 -0
  37. package/dist/lib/neutral/chunk-KRXHIW4P.mjs +164 -0
  38. package/dist/lib/neutral/chunk-KRXHIW4P.mjs.map +7 -0
  39. package/dist/lib/{browser/chunk-TPNZ43NB.mjs → neutral/chunk-PE7IH7EL.mjs} +86 -73
  40. package/dist/lib/neutral/chunk-PE7IH7EL.mjs.map +7 -0
  41. package/dist/lib/neutral/chunk-QFDT33VT.mjs +69 -0
  42. package/dist/lib/neutral/chunk-QFDT33VT.mjs.map +7 -0
  43. package/dist/lib/neutral/chunk-QMLVLKE3.mjs +8 -0
  44. package/dist/lib/neutral/chunk-QMLVLKE3.mjs.map +7 -0
  45. package/dist/lib/neutral/components/index.mjs +539 -0
  46. package/dist/lib/neutral/components/index.mjs.map +7 -0
  47. package/dist/lib/neutral/containers/index.mjs +15 -0
  48. package/dist/lib/neutral/containers/index.mjs.map +7 -0
  49. package/dist/lib/{browser/create-BTGLHLBA.mjs → neutral/create-OAQJ6LXN.mjs} +7 -10
  50. package/dist/lib/neutral/create-OAQJ6LXN.mjs.map +7 -0
  51. package/dist/lib/{browser/create-channel-ZXKSLHGN.mjs → neutral/create-channel-3E4FJ662.mjs} +4 -4
  52. package/dist/lib/neutral/create-channel-3E4FJ662.mjs.map +7 -0
  53. package/dist/lib/neutral/create-object-HIEWSBZB.mjs +27 -0
  54. package/dist/lib/neutral/create-object-HIEWSBZB.mjs.map +7 -0
  55. package/dist/lib/{browser/create-proposals-AV5CREPV.mjs → neutral/create-proposals-GRYZXRMV.mjs} +4 -4
  56. package/dist/lib/neutral/create-proposals-GRYZXRMV.mjs.map +7 -0
  57. package/dist/lib/{browser/delete-GLYEP7NE.mjs → neutral/delete-HCCG5RVR.mjs} +7 -9
  58. package/dist/lib/neutral/delete-HCCG5RVR.mjs.map +7 -0
  59. package/dist/lib/{browser/delete-message-RQ72ZY5D.mjs → neutral/delete-message-DHFRACB4.mjs} +6 -7
  60. package/dist/lib/neutral/delete-message-DHFRACB4.mjs.map +7 -0
  61. package/dist/lib/neutral/hooks/index.mjs +10 -0
  62. package/dist/lib/neutral/index.mjs +28 -0
  63. package/dist/lib/neutral/index.mjs.map +7 -0
  64. package/dist/lib/neutral/markdown-BUORNCPG.mjs +83 -0
  65. package/dist/lib/neutral/markdown-BUORNCPG.mjs.map +7 -0
  66. package/dist/lib/neutral/meta.json +1 -0
  67. package/dist/lib/neutral/meta.mjs +10 -0
  68. package/dist/lib/neutral/meta.mjs.map +7 -0
  69. package/dist/lib/{browser/on-create-space-SPE3QVFZ.mjs → neutral/on-create-space-OEBRKOAM.mjs} +5 -6
  70. package/dist/lib/neutral/on-create-space-OEBRKOAM.mjs.map +7 -0
  71. package/dist/lib/neutral/operation-handler-RU6K2S4L.mjs +13 -0
  72. package/dist/lib/neutral/operation-handler-RU6K2S4L.mjs.map +7 -0
  73. package/dist/lib/neutral/operations/index.mjs +8 -0
  74. package/dist/lib/neutral/operations/index.mjs.map +7 -0
  75. package/dist/lib/neutral/plugin.mjs +16 -0
  76. package/dist/lib/neutral/plugin.mjs.map +7 -0
  77. package/dist/lib/neutral/react-surface-XY23GVZH.mjs +76 -0
  78. package/dist/lib/neutral/react-surface-XY23GVZH.mjs.map +7 -0
  79. package/dist/lib/{browser/restore-VX7FLZOZ.mjs → neutral/restore-P4ZLXLF7.mjs} +5 -5
  80. package/dist/lib/neutral/restore-P4ZLXLF7.mjs.map +7 -0
  81. package/dist/lib/{browser/restore-message-D65NSWUA.mjs → neutral/restore-message-AUBOP2DF.mjs} +5 -5
  82. package/dist/lib/neutral/restore-message-AUBOP2DF.mjs.map +7 -0
  83. package/dist/lib/{browser/select-AT4L7EBU.mjs → neutral/select-LIVAMBCE.mjs} +6 -8
  84. package/dist/lib/neutral/select-LIVAMBCE.mjs.map +7 -0
  85. package/dist/lib/neutral/settings-HK4EB6TF.mjs +30 -0
  86. package/dist/lib/neutral/settings-HK4EB6TF.mjs.map +7 -0
  87. package/dist/lib/neutral/state-UU7VEAKV.mjs +22 -0
  88. package/dist/lib/neutral/state-UU7VEAKV.mjs.map +7 -0
  89. package/dist/lib/neutral/testing/index.mjs +58 -0
  90. package/dist/lib/neutral/testing/index.mjs.map +7 -0
  91. package/dist/lib/{browser/toggle-resolved-JD3D4WBZ.mjs → neutral/toggle-resolved-RQBDQZSV.mjs} +5 -5
  92. package/dist/lib/neutral/toggle-resolved-RQBDQZSV.mjs.map +7 -0
  93. package/dist/lib/{browser → neutral}/translations.mjs +2 -2
  94. package/dist/lib/neutral/translations.mjs.map +7 -0
  95. package/dist/lib/neutral/types/index.mjs +12 -0
  96. package/dist/lib/neutral/types/index.mjs.map +7 -0
  97. package/dist/lib/neutral/undo-mappings-HOKL2L3M.mjs +54 -0
  98. package/dist/lib/neutral/undo-mappings-HOKL2L3M.mjs.map +7 -0
  99. package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
  100. package/dist/types/src/ThreadPlugin.node.d.ts.map +1 -1
  101. package/dist/types/src/ThreadPlugin.workerd.d.ts +4 -0
  102. package/dist/types/src/ThreadPlugin.workerd.d.ts.map +1 -0
  103. package/dist/types/src/capabilities/create-object.d.ts +11 -0
  104. package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
  105. package/dist/types/src/capabilities/index.d.ts +7 -6
  106. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  107. package/dist/types/src/capabilities/markdown.d.ts +1 -1
  108. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  109. package/dist/types/src/capabilities/settings.d.ts.map +1 -1
  110. package/dist/types/src/components/Chat/Chat.d.ts +8 -1
  111. package/dist/types/src/components/Chat/Chat.d.ts.map +1 -1
  112. package/dist/types/src/components/CommentsPanel/CommentsThread.d.ts.map +1 -1
  113. package/dist/types/src/components/MessagePanel/MessagePanel.d.ts.map +1 -1
  114. package/dist/types/src/components/ThreadSettings/ThreadSettings.d.ts.map +1 -1
  115. package/dist/types/src/components/index.d.ts +0 -1
  116. package/dist/types/src/components/index.d.ts.map +1 -1
  117. package/dist/types/src/containers/ChannelArticle/ChannelArticle.d.ts +13 -0
  118. package/dist/types/src/containers/ChannelArticle/ChannelArticle.d.ts.map +1 -0
  119. package/dist/types/src/containers/{ChannelContainer/ChannelContainer.stories.d.ts → ChannelArticle/ChannelArticle.stories.d.ts} +4 -4
  120. package/dist/types/src/containers/ChannelArticle/ChannelArticle.stories.d.ts.map +1 -0
  121. package/dist/types/src/containers/ChannelArticle/index.d.ts +2 -0
  122. package/dist/types/src/containers/{CallDebugPanel → ChannelArticle}/index.d.ts.map +1 -1
  123. package/dist/types/src/containers/ChannelChat/ChannelChat.d.ts +4 -0
  124. package/dist/types/src/containers/ChannelChat/ChannelChat.d.ts.map +1 -1
  125. package/dist/types/src/containers/ThreadCompanion/ThreadCompanion.d.ts.map +1 -1
  126. package/dist/types/src/containers/index.d.ts +1 -3
  127. package/dist/types/src/containers/index.d.ts.map +1 -1
  128. package/dist/types/src/extensions/threads.d.ts +1 -1
  129. package/dist/types/src/extensions/threads.d.ts.map +1 -1
  130. package/dist/types/src/hooks/index.d.ts +0 -4
  131. package/dist/types/src/hooks/index.d.ts.map +1 -1
  132. package/dist/types/src/index.d.ts +3 -5
  133. package/dist/types/src/index.d.ts.map +1 -1
  134. package/dist/types/src/meta.d.ts.map +1 -1
  135. package/dist/types/src/operations/add-message.d.ts +2 -2
  136. package/dist/types/src/operations/add-message.d.ts.map +1 -1
  137. package/dist/types/src/operations/append-channel-message.d.ts +2 -2
  138. package/dist/types/src/operations/append-channel-message.d.ts.map +1 -1
  139. package/dist/types/src/operations/create-channel.d.ts +2 -2
  140. package/dist/types/src/operations/create-channel.d.ts.map +1 -1
  141. package/dist/types/src/operations/create-proposals.d.ts +2 -2
  142. package/dist/types/src/operations/create-proposals.d.ts.map +1 -1
  143. package/dist/types/src/operations/create.d.ts +2 -2
  144. package/dist/types/src/operations/create.d.ts.map +1 -1
  145. package/dist/types/src/operations/delete-message.d.ts +2 -2
  146. package/dist/types/src/operations/delete-message.d.ts.map +1 -1
  147. package/dist/types/src/operations/delete.d.ts +2 -2
  148. package/dist/types/src/operations/delete.d.ts.map +1 -1
  149. package/dist/types/src/operations/index.d.ts +0 -1
  150. package/dist/types/src/operations/index.d.ts.map +1 -1
  151. package/dist/types/src/operations/on-create-space.d.ts +2 -2
  152. package/dist/types/src/operations/on-create-space.d.ts.map +1 -1
  153. package/dist/types/src/operations/restore-message.d.ts +2 -2
  154. package/dist/types/src/operations/restore-message.d.ts.map +1 -1
  155. package/dist/types/src/operations/restore.d.ts +2 -2
  156. package/dist/types/src/operations/restore.d.ts.map +1 -1
  157. package/dist/types/src/operations/select.d.ts +2 -2
  158. package/dist/types/src/operations/select.d.ts.map +1 -1
  159. package/dist/types/src/operations/toggle-resolved.d.ts +2 -2
  160. package/dist/types/src/operations/toggle-resolved.d.ts.map +1 -1
  161. package/dist/types/src/plugin.d.ts +4 -0
  162. package/dist/types/src/plugin.d.ts.map +1 -0
  163. package/dist/types/src/translations.d.ts.map +1 -1
  164. package/dist/types/src/types/ThreadCapabilities.d.ts +13 -0
  165. package/dist/types/src/types/ThreadCapabilities.d.ts.map +1 -0
  166. package/dist/types/src/{operations/definitions.d.ts → types/ThreadOperation.d.ts} +1 -1
  167. package/dist/types/src/types/ThreadOperation.d.ts.map +1 -0
  168. package/dist/types/src/types/index.d.ts +3 -1
  169. package/dist/types/src/types/index.d.ts.map +1 -1
  170. package/dist/types/src/types/types.d.ts +1 -1
  171. package/dist/types/src/types/types.d.ts.map +1 -1
  172. package/dist/types/src/util.d.ts +4 -1
  173. package/dist/types/src/util.d.ts.map +1 -1
  174. package/dist/types/tsconfig.tsbuildinfo +1 -1
  175. package/package.json +123 -99
  176. package/src/ThreadPlugin.node.ts +5 -50
  177. package/src/ThreadPlugin.test.ts +3 -3
  178. package/src/ThreadPlugin.tsx +6 -59
  179. package/src/ThreadPlugin.workerd.ts +20 -0
  180. package/src/blueprints/thread-blueprint.ts +1 -1
  181. package/src/capabilities/app-graph-builder.ts +18 -69
  182. package/src/capabilities/create-object.ts +29 -0
  183. package/src/capabilities/index.ts +1 -2
  184. package/src/capabilities/markdown.ts +1 -1
  185. package/src/capabilities/react-surface.tsx +4 -26
  186. package/src/capabilities/settings.ts +1 -3
  187. package/src/capabilities/undo-mappings.ts +1 -1
  188. package/src/components/Chat/Chat.tsx +52 -12
  189. package/src/components/CommentsPanel/CommentsPanel.stories.tsx +1 -1
  190. package/src/components/CommentsPanel/CommentsPanel.tsx +4 -4
  191. package/src/components/CommentsPanel/CommentsThread.tsx +2 -3
  192. package/src/components/MessagePanel/MessagePanel.tsx +7 -8
  193. package/src/components/ThreadSettings/ThreadSettings.tsx +0 -1
  194. package/src/components/index.ts +0 -1
  195. package/src/containers/{ChannelContainer/ChannelContainer.stories.tsx → ChannelArticle/ChannelArticle.stories.tsx} +10 -10
  196. package/src/containers/ChannelArticle/ChannelArticle.tsx +42 -0
  197. package/src/containers/ChannelArticle/index.ts +5 -0
  198. package/src/containers/ChannelChat/ChannelChat.tsx +12 -2
  199. package/src/containers/ThreadCompanion/ThreadCompanion.tsx +10 -12
  200. package/src/containers/index.ts +1 -3
  201. package/src/extensions/command.ts +1 -1
  202. package/src/extensions/threads.ts +2 -2
  203. package/src/hooks/analytics.ts +1 -1
  204. package/src/hooks/index.ts +0 -5
  205. package/src/index.ts +3 -10
  206. package/src/meta.ts +1 -2
  207. package/src/operations/add-message.ts +4 -4
  208. package/src/operations/append-channel-message.ts +20 -19
  209. package/src/operations/create-channel.ts +2 -2
  210. package/src/operations/create-proposals.ts +2 -2
  211. package/src/operations/create.ts +3 -3
  212. package/src/operations/delete-message.ts +4 -4
  213. package/src/operations/delete.ts +3 -3
  214. package/src/operations/index.ts +0 -2
  215. package/src/operations/on-create-space.ts +3 -3
  216. package/src/operations/restore-message.ts +3 -3
  217. package/src/operations/restore.ts +3 -3
  218. package/src/operations/select.ts +2 -2
  219. package/src/operations/toggle-resolved.ts +3 -3
  220. package/src/plugin.ts +11 -0
  221. package/src/translations.ts +2 -2
  222. package/src/types/ThreadCapabilities.ts +26 -0
  223. package/src/{operations/definitions.ts → types/ThreadOperation.ts} +5 -4
  224. package/src/types/index.ts +4 -1
  225. package/src/types/types.ts +0 -2
  226. package/src/util.ts +36 -4
  227. package/dist/lib/browser/add-message-LRVGIHDH.mjs.map +0 -7
  228. package/dist/lib/browser/append-channel-message-CO3M6FSA.mjs.map +0 -7
  229. package/dist/lib/browser/blueprints/index.mjs.map +0 -7
  230. package/dist/lib/browser/chunk-E4GG3NX2.mjs +0 -29
  231. package/dist/lib/browser/chunk-E4GG3NX2.mjs.map +0 -7
  232. package/dist/lib/browser/chunk-TPNZ43NB.mjs.map +0 -7
  233. package/dist/lib/browser/create-BTGLHLBA.mjs.map +0 -7
  234. package/dist/lib/browser/create-channel-ZXKSLHGN.mjs.map +0 -7
  235. package/dist/lib/browser/create-proposals-AV5CREPV.mjs.map +0 -7
  236. package/dist/lib/browser/delete-GLYEP7NE.mjs.map +0 -7
  237. package/dist/lib/browser/delete-message-RQ72ZY5D.mjs.map +0 -7
  238. package/dist/lib/browser/index.mjs +0 -1821
  239. package/dist/lib/browser/index.mjs.map +0 -7
  240. package/dist/lib/browser/meta.json +0 -1
  241. package/dist/lib/browser/on-create-space-SPE3QVFZ.mjs.map +0 -7
  242. package/dist/lib/browser/operations/index.mjs +0 -13
  243. package/dist/lib/browser/operations/index.mjs.map +0 -7
  244. package/dist/lib/browser/restore-VX7FLZOZ.mjs.map +0 -7
  245. package/dist/lib/browser/restore-message-D65NSWUA.mjs.map +0 -7
  246. package/dist/lib/browser/select-AT4L7EBU.mjs.map +0 -7
  247. package/dist/lib/browser/toggle-resolved-JD3D4WBZ.mjs.map +0 -7
  248. package/dist/lib/browser/translations.mjs.map +0 -7
  249. package/dist/lib/browser/types/index.mjs +0 -10
  250. package/dist/lib/node-esm/add-message-4EAQ2ZPI.mjs +0 -90
  251. package/dist/lib/node-esm/add-message-4EAQ2ZPI.mjs.map +0 -7
  252. package/dist/lib/node-esm/append-channel-message-F7KGBSWP.mjs +0 -41
  253. package/dist/lib/node-esm/append-channel-message-F7KGBSWP.mjs.map +0 -7
  254. package/dist/lib/node-esm/blueprints/index.mjs +0 -38
  255. package/dist/lib/node-esm/blueprints/index.mjs.map +0 -7
  256. package/dist/lib/node-esm/chunk-BVEZBGIY.mjs +0 -30
  257. package/dist/lib/node-esm/chunk-BVEZBGIY.mjs.map +0 -7
  258. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
  259. package/dist/lib/node-esm/chunk-XKUMDYGR.mjs +0 -259
  260. package/dist/lib/node-esm/chunk-XKUMDYGR.mjs.map +0 -7
  261. package/dist/lib/node-esm/create-DEZFPN2Y.mjs +0 -56
  262. package/dist/lib/node-esm/create-DEZFPN2Y.mjs.map +0 -7
  263. package/dist/lib/node-esm/create-channel-6VHTC2OR.mjs +0 -20
  264. package/dist/lib/node-esm/create-channel-6VHTC2OR.mjs.map +0 -7
  265. package/dist/lib/node-esm/create-proposals-P5O2ICOL.mjs +0 -57
  266. package/dist/lib/node-esm/create-proposals-P5O2ICOL.mjs.map +0 -7
  267. package/dist/lib/node-esm/delete-QG45QLPY.mjs +0 -60
  268. package/dist/lib/node-esm/delete-QG45QLPY.mjs.map +0 -7
  269. package/dist/lib/node-esm/delete-message-PGNLB6TL.mjs +0 -56
  270. package/dist/lib/node-esm/delete-message-PGNLB6TL.mjs.map +0 -7
  271. package/dist/lib/node-esm/index.mjs +0 -1822
  272. package/dist/lib/node-esm/index.mjs.map +0 -7
  273. package/dist/lib/node-esm/meta.json +0 -1
  274. package/dist/lib/node-esm/on-create-space-TFBSHWQ4.mjs +0 -25
  275. package/dist/lib/node-esm/on-create-space-TFBSHWQ4.mjs.map +0 -7
  276. package/dist/lib/node-esm/operations/index.mjs +0 -14
  277. package/dist/lib/node-esm/operations/index.mjs.map +0 -7
  278. package/dist/lib/node-esm/restore-E27OAIFJ.mjs +0 -33
  279. package/dist/lib/node-esm/restore-E27OAIFJ.mjs.map +0 -7
  280. package/dist/lib/node-esm/restore-message-J3CH6NGI.mjs +0 -34
  281. package/dist/lib/node-esm/restore-message-J3CH6NGI.mjs.map +0 -7
  282. package/dist/lib/node-esm/select-UU6Q2XAB.mjs +0 -27
  283. package/dist/lib/node-esm/select-UU6Q2XAB.mjs.map +0 -7
  284. package/dist/lib/node-esm/toggle-resolved-VS6NKXL3.mjs +0 -37
  285. package/dist/lib/node-esm/toggle-resolved-VS6NKXL3.mjs.map +0 -7
  286. package/dist/lib/node-esm/translations.mjs +0 -91
  287. package/dist/lib/node-esm/translations.mjs.map +0 -7
  288. package/dist/lib/node-esm/types/index.mjs +0 -11
  289. package/dist/types/src/calls/call-manager.d.ts +0 -87
  290. package/dist/types/src/calls/call-manager.d.ts.map +0 -1
  291. package/dist/types/src/calls/call-swarm-synchronizer.d.ts +0 -66
  292. package/dist/types/src/calls/call-swarm-synchronizer.d.ts.map +0 -1
  293. package/dist/types/src/calls/index.d.ts +0 -7
  294. package/dist/types/src/calls/index.d.ts.map +0 -1
  295. package/dist/types/src/calls/media-manager.d.ts +0 -60
  296. package/dist/types/src/calls/media-manager.d.ts.map +0 -1
  297. package/dist/types/src/calls/speaking-monitor.d.ts +0 -21
  298. package/dist/types/src/calls/speaking-monitor.d.ts.map +0 -1
  299. package/dist/types/src/calls/types.d.ts +0 -45
  300. package/dist/types/src/calls/types.d.ts.map +0 -1
  301. package/dist/types/src/calls/util/audio.d.ts +0 -6
  302. package/dist/types/src/calls/util/audio.d.ts.map +0 -1
  303. package/dist/types/src/calls/util/calls-service.d.ts +0 -77
  304. package/dist/types/src/calls/util/calls-service.d.ts.map +0 -1
  305. package/dist/types/src/calls/util/history-cache.d.ts +0 -11
  306. package/dist/types/src/calls/util/history-cache.d.ts.map +0 -1
  307. package/dist/types/src/calls/util/index.d.ts +0 -5
  308. package/dist/types/src/calls/util/index.d.ts.map +0 -1
  309. package/dist/types/src/calls/util/media.d.ts +0 -6
  310. package/dist/types/src/calls/util/media.d.ts.map +0 -1
  311. package/dist/types/src/calls/util/stub-media-streams.d.ts +0 -18
  312. package/dist/types/src/calls/util/stub-media-streams.d.ts.map +0 -1
  313. package/dist/types/src/calls/util/task-scheduling.d.ts +0 -17
  314. package/dist/types/src/calls/util/task-scheduling.d.ts.map +0 -1
  315. package/dist/types/src/calls-service.stories.d.ts +0 -23
  316. package/dist/types/src/calls-service.stories.d.ts.map +0 -1
  317. package/dist/types/src/capabilities/call-manager.d.ts +0 -6
  318. package/dist/types/src/capabilities/call-manager.d.ts.map +0 -1
  319. package/dist/types/src/capabilities/react-root.d.ts +0 -9
  320. package/dist/types/src/capabilities/react-root.d.ts.map +0 -1
  321. package/dist/types/src/components/Call/Call.d.ts +0 -45
  322. package/dist/types/src/components/Call/Call.d.ts.map +0 -1
  323. package/dist/types/src/components/Call/Toolbar.d.ts +0 -16
  324. package/dist/types/src/components/Call/Toolbar.d.ts.map +0 -1
  325. package/dist/types/src/components/Call/index.d.ts +0 -3
  326. package/dist/types/src/components/Call/index.d.ts.map +0 -1
  327. package/dist/types/src/components/Lobby/Lobby.d.ts +0 -36
  328. package/dist/types/src/components/Lobby/Lobby.d.ts.map +0 -1
  329. package/dist/types/src/components/Lobby/index.d.ts +0 -2
  330. package/dist/types/src/components/Lobby/index.d.ts.map +0 -1
  331. package/dist/types/src/components/Media/AudioStream.d.ts +0 -6
  332. package/dist/types/src/components/Media/AudioStream.d.ts.map +0 -1
  333. package/dist/types/src/components/Media/VideoObject.d.ts +0 -15
  334. package/dist/types/src/components/Media/VideoObject.d.ts.map +0 -1
  335. package/dist/types/src/components/Media/VideoObject.stories.d.ts +0 -22
  336. package/dist/types/src/components/Media/VideoObject.stories.d.ts.map +0 -1
  337. package/dist/types/src/components/Media/index.d.ts +0 -3
  338. package/dist/types/src/components/Media/index.d.ts.map +0 -1
  339. package/dist/types/src/components/Participant/Participant.d.ts +0 -6
  340. package/dist/types/src/components/Participant/Participant.d.ts.map +0 -1
  341. package/dist/types/src/components/Participant/ParticipantGrid.d.ts +0 -11
  342. package/dist/types/src/components/Participant/ParticipantGrid.d.ts.map +0 -1
  343. package/dist/types/src/components/Participant/index.d.ts +0 -3
  344. package/dist/types/src/components/Participant/index.d.ts.map +0 -1
  345. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.d.ts +0 -32
  346. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.d.ts.map +0 -1
  347. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts +0 -178
  348. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts.map +0 -1
  349. package/dist/types/src/components/ResponsiveGrid/ResponsiveGridItem.d.ts +0 -21
  350. package/dist/types/src/components/ResponsiveGrid/ResponsiveGridItem.d.ts.map +0 -1
  351. package/dist/types/src/components/ResponsiveGrid/ResponsivePanel.d.ts +0 -12
  352. package/dist/types/src/components/ResponsiveGrid/ResponsivePanel.d.ts.map +0 -1
  353. package/dist/types/src/components/ResponsiveGrid/ResponsivePanel.stories.d.ts +0 -164
  354. package/dist/types/src/components/ResponsiveGrid/ResponsivePanel.stories.d.ts.map +0 -1
  355. package/dist/types/src/components/ResponsiveGrid/index.d.ts +0 -4
  356. package/dist/types/src/components/ResponsiveGrid/index.d.ts.map +0 -1
  357. package/dist/types/src/containers/CallDebugPanel/CallDebugPanel.d.ts +0 -15
  358. package/dist/types/src/containers/CallDebugPanel/CallDebugPanel.d.ts.map +0 -1
  359. package/dist/types/src/containers/CallDebugPanel/index.d.ts +0 -2
  360. package/dist/types/src/containers/CallSidebar/CallSidebar.d.ts +0 -3
  361. package/dist/types/src/containers/CallSidebar/CallSidebar.d.ts.map +0 -1
  362. package/dist/types/src/containers/CallSidebar/index.d.ts +0 -2
  363. package/dist/types/src/containers/CallSidebar/index.d.ts.map +0 -1
  364. package/dist/types/src/containers/ChannelContainer/ChannelContainer.d.ts +0 -12
  365. package/dist/types/src/containers/ChannelContainer/ChannelContainer.d.ts.map +0 -1
  366. package/dist/types/src/containers/ChannelContainer/ChannelContainer.stories.d.ts.map +0 -1
  367. package/dist/types/src/containers/ChannelContainer/index.d.ts +0 -2
  368. package/dist/types/src/containers/ChannelContainer/index.d.ts.map +0 -1
  369. package/dist/types/src/hooks/useBlackCanvasStreamTrack.d.ts +0 -2
  370. package/dist/types/src/hooks/useBlackCanvasStreamTrack.d.ts.map +0 -1
  371. package/dist/types/src/hooks/useDebugMode.d.ts +0 -2
  372. package/dist/types/src/hooks/useDebugMode.d.ts.map +0 -1
  373. package/dist/types/src/hooks/useInaudibleAudioStreamTrack.d.ts +0 -2
  374. package/dist/types/src/hooks/useInaudibleAudioStreamTrack.d.ts.map +0 -1
  375. package/dist/types/src/hooks/useVideoStreamTrack.d.ts +0 -3
  376. package/dist/types/src/hooks/useVideoStreamTrack.d.ts.map +0 -1
  377. package/dist/types/src/operations/definitions.d.ts.map +0 -1
  378. package/dist/types/src/types/capabilities.d.ts +0 -25
  379. package/dist/types/src/types/capabilities.d.ts.map +0 -1
  380. package/src/calls/call-manager.ts +0 -270
  381. package/src/calls/call-swarm-synchronizer.ts +0 -350
  382. package/src/calls/index.ts +0 -10
  383. package/src/calls/media-manager.ts +0 -378
  384. package/src/calls/speaking-monitor.ts +0 -85
  385. package/src/calls/types.ts +0 -74
  386. package/src/calls/util/audio.ts +0 -58
  387. package/src/calls/util/calls-service.ts +0 -582
  388. package/src/calls/util/history-cache.ts +0 -27
  389. package/src/calls/util/index.ts +0 -8
  390. package/src/calls/util/media.ts +0 -52
  391. package/src/calls/util/stub-media-streams.ts +0 -129
  392. package/src/calls/util/task-scheduling.ts +0 -92
  393. package/src/calls-service.stories.tsx +0 -230
  394. package/src/capabilities/call-manager.ts +0 -27
  395. package/src/capabilities/react-root.tsx +0 -20
  396. package/src/components/Call/Call.tsx +0 -93
  397. package/src/components/Call/Toolbar.tsx +0 -199
  398. package/src/components/Call/index.ts +0 -6
  399. package/src/components/Lobby/Lobby.tsx +0 -123
  400. package/src/components/Lobby/index.ts +0 -5
  401. package/src/components/Media/AudioStream.tsx +0 -67
  402. package/src/components/Media/VideoObject.stories.tsx +0 -59
  403. package/src/components/Media/VideoObject.tsx +0 -58
  404. package/src/components/Media/index.ts +0 -6
  405. package/src/components/Participant/Participant.tsx +0 -77
  406. package/src/components/Participant/ParticipantGrid.tsx +0 -88
  407. package/src/components/Participant/index.ts +0 -6
  408. package/src/components/ResponsiveGrid/ResponsiveGrid.stories.tsx +0 -158
  409. package/src/components/ResponsiveGrid/ResponsiveGrid.tsx +0 -341
  410. package/src/components/ResponsiveGrid/ResponsiveGridItem.tsx +0 -134
  411. package/src/components/ResponsiveGrid/ResponsivePanel.stories.tsx +0 -54
  412. package/src/components/ResponsiveGrid/ResponsivePanel.tsx +0 -31
  413. package/src/components/ResponsiveGrid/index.ts +0 -7
  414. package/src/containers/CallDebugPanel/CallDebugPanel.tsx +0 -173
  415. package/src/containers/CallDebugPanel/index.ts +0 -5
  416. package/src/containers/CallSidebar/CallSidebar.tsx +0 -18
  417. package/src/containers/CallSidebar/index.ts +0 -5
  418. package/src/containers/ChannelContainer/ChannelContainer.tsx +0 -223
  419. package/src/containers/ChannelContainer/index.ts +0 -5
  420. package/src/hooks/useBlackCanvasStreamTrack.tsx +0 -27
  421. package/src/hooks/useDebugMode.ts +0 -25
  422. package/src/hooks/useInaudibleAudioStreamTrack.tsx +0 -27
  423. package/src/hooks/useVideoStreamTrack.tsx +0 -36
  424. package/src/types/capabilities.ts +0 -37
  425. package/src/typings/peermetrics-webrtc-stats.d.ts +0 -46
  426. package/src/typings.d.ts +0 -8
  427. /package/dist/lib/{browser/chunk-J5LGTIGS.mjs.map → neutral/ChannelChat-6YTD5HWL.mjs.map} +0 -0
  428. /package/dist/lib/{browser/types → neutral/blueprints}/index.mjs.map +0 -0
  429. /package/dist/lib/{browser → neutral}/chunk-J5LGTIGS.mjs +0 -0
  430. /package/dist/lib/{node-esm/chunk-HSLMI22Q.mjs.map → neutral/chunk-J5LGTIGS.mjs.map} +0 -0
  431. /package/dist/lib/{node-esm/types → neutral/hooks}/index.mjs.map +0 -0
@@ -1,270 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import { Atom, type Registry } from '@effect-atom/atom-react';
6
-
7
- import { Event, synchronized } from '@dxos/async';
8
- import { type Client } from '@dxos/client';
9
- import { Resource } from '@dxos/context';
10
- import { invariant } from '@dxos/invariant';
11
- import { type Tracks } from '@dxos/protocols/proto/dxos/edge/calls';
12
- import { isNonNullable } from '@dxos/util';
13
-
14
- import { type CallState, CallSwarmSynchronizer } from './call-swarm-synchronizer';
15
- import { MediaManager, type MediaState } from './media-manager';
16
- import { type ActivityState, CALLS_URL, type EncodedTrackName, TrackNameCodec, type UserState } from './types';
17
-
18
- export type GlobalState = {
19
- call: CallState;
20
- media: MediaState;
21
- };
22
-
23
- /**
24
- * Top level manager for call state.
25
- */
26
- export class CallManager extends Resource {
27
- public readonly callStateUpdated = new Event<CallState>();
28
- // TODO(wittjosiah): Consolidate isSpeaking into the MediaState type.
29
- public readonly mediaStateUpdated = new Event<[MediaState, boolean]>();
30
- public readonly left = new Event<string>();
31
-
32
- /**
33
- * Atom-based state. Updated via `_updateState()`.
34
- * CAUTION: Do not change directly.
35
- */
36
- private readonly _stateAtom = Atom.make<GlobalState>({
37
- call: {},
38
- media: { pulledAudioTracks: {}, pulledVideoStreams: {} },
39
- });
40
-
41
- // Derived atoms for reactive subscriptions.
42
- private readonly _roomIdAtom = Atom.make((get) => get(this._stateAtom).call.roomId);
43
- private readonly _raisedHandAtom = Atom.make((get) => get(this._stateAtom).call.raisedHand ?? false);
44
- private readonly _speakingAtom = Atom.make((get) => get(this._stateAtom).call.speaking ?? false);
45
- private readonly _joinedAtom = Atom.make((get) => get(this._stateAtom).call.joined ?? false);
46
- private readonly _selfAtom = Atom.make((get) => get(this._stateAtom).call.self ?? {});
47
- private readonly _tracksAtom = Atom.make((get) => get(this._stateAtom).call.tracks ?? {});
48
- private readonly _usersAtom = Atom.make((get) => get(this._stateAtom).call.users ?? []);
49
- private readonly _mediaAtom = Atom.make((get) => get(this._stateAtom).media);
50
- private readonly _audioTracksToPlayAtom = Atom.make((get) => {
51
- const state = get(this._stateAtom);
52
- return (state.call.users ?? [])
53
- .map((user: UserState) => (user.tracks?.audioEnabled ? user.tracks?.audio : undefined))
54
- .filter(isNonNullable)
55
- .map((track: string) => state.media.pulledAudioTracks[track as EncodedTrackName]?.track)
56
- .filter(isNonNullable);
57
- });
58
- private readonly _videoStreamAtomFamily = Atom.family<EncodedTrackName, Atom.Atom<MediaStream | undefined>>((name) =>
59
- Atom.make((get) => get(this._stateAtom).media.pulledVideoStreams[name]?.stream),
60
- );
61
- private readonly _activityAtomFamily = Atom.family<string, Atom.Atom<ActivityState | undefined>>((key) =>
62
- Atom.make((get) => get(this._stateAtom).call.activities?.[key]),
63
- );
64
-
65
- private readonly _swarmSynchronizer: CallSwarmSynchronizer;
66
- private readonly _mediaManager: MediaManager;
67
-
68
- //
69
- // Derived atoms for reactive UI subscriptions.
70
- //
71
-
72
- /** Derived atom for roomId. */
73
- get roomIdAtom(): Atom.Atom<string | undefined> {
74
- return this._roomIdAtom;
75
- }
76
-
77
- /** Derived atom for raisedHand. */
78
- get raisedHandAtom(): Atom.Atom<boolean> {
79
- return this._raisedHandAtom;
80
- }
81
-
82
- /** Derived atom for speaking. */
83
- get speakingAtom(): Atom.Atom<boolean> {
84
- return this._speakingAtom;
85
- }
86
-
87
- /** Derived atom for joined. */
88
- get joinedAtom(): Atom.Atom<boolean> {
89
- return this._joinedAtom;
90
- }
91
-
92
- /** Derived atom for self. */
93
- get selfAtom(): Atom.Atom<UserState> {
94
- return this._selfAtom;
95
- }
96
-
97
- /** Derived atom for tracks. */
98
- get tracksAtom(): Atom.Atom<Tracks> {
99
- return this._tracksAtom;
100
- }
101
-
102
- /** Derived atom for users. */
103
- get usersAtom(): Atom.Atom<UserState[]> {
104
- return this._usersAtom;
105
- }
106
-
107
- /** Derived atom for media. */
108
- get mediaAtom(): Atom.Atom<MediaState> {
109
- return this._mediaAtom;
110
- }
111
-
112
- /** Derived atom for audioTracksToPlay. */
113
- get audioTracksToPlayAtom(): Atom.Atom<MediaStreamTrack[]> {
114
- return this._audioTracksToPlayAtom;
115
- }
116
-
117
- /** Returns the full state atom for reactive subscriptions. */
118
- get stateAtom(): Atom.Atom<GlobalState> {
119
- return this._stateAtom;
120
- }
121
-
122
- /** Returns a derived atom for a video stream by name. */
123
- videoStreamAtom(name: EncodedTrackName): Atom.Atom<MediaStream | undefined> {
124
- return this._videoStreamAtomFamily(name);
125
- }
126
-
127
- /** Returns a derived atom for an activity by key. */
128
- activityAtom(key: string): Atom.Atom<ActivityState | undefined> {
129
- return this._activityAtomFamily(key);
130
- }
131
-
132
- setRoomId(roomId: string): void {
133
- this._swarmSynchronizer._setRoomId(roomId);
134
- }
135
-
136
- setSpeaking(speaking: boolean): void {
137
- this._swarmSynchronizer.setSpeaking(speaking);
138
- }
139
-
140
- setRaisedHand(raisedHand: boolean): void {
141
- this._swarmSynchronizer.setRaisedHand(raisedHand);
142
- }
143
-
144
- setActivity(key: string, payload: ActivityState['payload']): void {
145
- this._swarmSynchronizer.setActivity(key, payload);
146
- }
147
-
148
- turnAudioOn(): Promise<void> {
149
- return this._mediaManager.turnAudioOn();
150
- }
151
-
152
- turnAudioOff(): Promise<void> {
153
- return this._mediaManager.turnAudioOff();
154
- }
155
-
156
- turnVideoOn(): Promise<void> {
157
- return this._mediaManager.turnVideoOn();
158
- }
159
-
160
- turnVideoOff(): Promise<void> {
161
- return this._mediaManager.turnVideoOff();
162
- }
163
-
164
- turnScreenshareOn(): Promise<void> {
165
- return this._mediaManager.turnScreenshareOn();
166
- }
167
-
168
- turnScreenshareOff(): Promise<void> {
169
- return this._mediaManager.turnScreenshareOff();
170
- }
171
-
172
- // TODO(burdon): Can this be mocked?
173
- constructor(
174
- private readonly _client: Client,
175
- private readonly _registry: Registry.Registry,
176
- ) {
177
- super();
178
- this._client.config.getOrThrow('runtime.services.edge.url');
179
- const networkService = this._client.services.services.NetworkService;
180
- invariant(networkService, 'network service not found');
181
- this._swarmSynchronizer = new CallSwarmSynchronizer({ networkService });
182
- this._mediaManager = new MediaManager();
183
- }
184
-
185
- protected override async _open(): Promise<void> {
186
- await this._mediaManager.open();
187
- await this._swarmSynchronizer.open();
188
- const subscription = this._client.halo.identity.subscribe((identity) => {
189
- if (identity) {
190
- this._swarmSynchronizer._setIdentity(identity);
191
- }
192
- if (this._client.halo.device) {
193
- this._swarmSynchronizer._setDevice(this._client.halo.device);
194
- }
195
- });
196
- this._ctx.onDispose(() => subscription.unsubscribe());
197
-
198
- this._swarmSynchronizer.stateUpdated.on(this._ctx, (state) => this._onCallStateUpdated(state));
199
- this._mediaManager.stateUpdated.on(this._ctx, (state) => this._onMediaStateUpdated(state));
200
- }
201
-
202
- protected override async _close(): Promise<void> {
203
- await this._swarmSynchronizer.leave();
204
- await this._swarmSynchronizer.close();
205
- await this._mediaManager.close();
206
- }
207
-
208
- async peek(roomId: string): Promise<number> {
209
- const peers = await this._swarmSynchronizer.querySwarm(roomId);
210
- return peers.length;
211
- }
212
-
213
- // TODO(mykola): Reconcile with _swarmSynchronizer.state.joined.
214
- @synchronized
215
- async join(): Promise<void> {
216
- this._swarmSynchronizer.setJoined(true);
217
- await this._swarmSynchronizer.join();
218
- await this._mediaManager.join({
219
- iceServers: this._client.config.get('runtime.services.ice'),
220
- apiBase: `${CALLS_URL}/api/calls`,
221
- });
222
- }
223
-
224
- @synchronized
225
- async leave(): Promise<void> {
226
- this._swarmSynchronizer.setJoined(false);
227
- await this._swarmSynchronizer.leave();
228
- await this._mediaManager.leave();
229
- const roomId = this._registry.get(this._roomIdAtom);
230
- roomId && this.left.emit(roomId);
231
- }
232
-
233
- private _onCallStateUpdated(state: CallState): void {
234
- const tracksToPull = state.users
235
- ?.filter((user) => user.joined && user.id !== state.self!.id)
236
- ?.flatMap((user) => [user.tracks?.video, user.tracks?.audio, user.tracks?.screenshare])
237
- .filter(isNonNullable);
238
- this._mediaManager._schedulePullTracks(tracksToPull as EncodedTrackName[]);
239
-
240
- this.callStateUpdated.emit(state);
241
- this._updateState();
242
- }
243
-
244
- private _onMediaStateUpdated(state: MediaState): void {
245
- this._swarmSynchronizer.setTracks({
246
- video: state.pushedVideoTrack ? TrackNameCodec.encode(state.pushedVideoTrack) : undefined,
247
- audio: state.pushedAudioTrack ? TrackNameCodec.encode(state.pushedAudioTrack) : undefined,
248
- screenshare: state.pushedScreenshareTrack ? TrackNameCodec.encode(state.pushedScreenshareTrack) : undefined,
249
- videoEnabled: state.videoEnabled,
250
- audioEnabled: state.audioEnabled,
251
- screenshareEnabled: state.screenshareEnabled,
252
- });
253
-
254
- const isSpeaking = this._mediaManager.isSpeaking ?? false;
255
- this._swarmSynchronizer.setSpeaking(isSpeaking);
256
-
257
- this.mediaStateUpdated.emit([state, isSpeaking]);
258
- this._updateState();
259
- }
260
-
261
- /**
262
- * Only this method is allowed to change state.
263
- */
264
- private _updateState(): void {
265
- this._registry.set(this._stateAtom, {
266
- call: this._swarmSynchronizer._getState(),
267
- media: this._mediaManager._getState(),
268
- });
269
- }
270
- }
@@ -1,350 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import md5Hex from 'md5-hex';
6
-
7
- import { DeferredTask, Event, scheduleTaskInterval, synchronized } from '@dxos/async';
8
- import { type Identity } from '@dxos/client/halo';
9
- import { Context, Resource } from '@dxos/context';
10
- import { generateName } from '@dxos/display-name';
11
- import { invariant } from '@dxos/invariant';
12
- import { PublicKey } from '@dxos/keys';
13
- import { log } from '@dxos/log';
14
- import { buf } from '@dxos/protocols/buf';
15
- import { ActivitySchema } from '@dxos/protocols/buf/dxos/edge/calls_pb';
16
- import { type Device, type NetworkService } from '@dxos/protocols/proto/dxos/client/services';
17
- import { ConnectionState, type SwarmResponse } from '@dxos/protocols/proto/dxos/edge/messenger';
18
- import { isNonNullable } from '@dxos/util';
19
-
20
- import { type ActivityState, type UserState, codec } from './types';
21
-
22
- export type CallState = {
23
- /**
24
- * Room id.
25
- */
26
- roomId?: string;
27
-
28
- /**
29
- * All users states in the swarm.
30
- */
31
- users?: UserState[];
32
-
33
- /**
34
- * Self state inside swarm.
35
- */
36
- self?: UserState;
37
-
38
- /**
39
- * Swarm synchronized CRDT transcription. Last write wins.
40
- */
41
- activities?: Record<string, ActivityState>;
42
-
43
- raisedHand?: boolean;
44
- speaking?: boolean;
45
- joined?: boolean;
46
-
47
- /**
48
- * Tracks pushed by self to calls service.
49
- */
50
- tracks?: UserState['tracks'];
51
- };
52
-
53
- export type CallSwarmSynchronizerProps = { networkService: NetworkService };
54
-
55
- /**
56
- * Period for peer to reconnect to the call swarm gracefully if connection was lost abruptly.
57
- */
58
- const DISCONNECTED_ABRUPT_TIMEOUT = 10_000; // [ms]
59
-
60
- /**
61
- * Sends and receives state to/from Swarm network.
62
- */
63
- export class CallSwarmSynchronizer extends Resource {
64
- public readonly stateUpdated = new Event<CallState>();
65
-
66
- private readonly _state: CallState = { activities: {} };
67
- private readonly _networkService: NetworkService;
68
- private _lastSwarmEvent?: SwarmResponse = undefined;
69
- private _reconcileSwarmStateTask?: DeferredTask = undefined;
70
-
71
- private _identityKey?: string = undefined;
72
- private _deviceKey?: string = undefined;
73
- private _displayName?: string = undefined;
74
-
75
- private _swarmCtx?: Context = undefined;
76
-
77
- private _sendStateTask?: DeferredTask = undefined;
78
-
79
- constructor({ networkService }: CallSwarmSynchronizerProps) {
80
- super();
81
- this._networkService = networkService;
82
- }
83
-
84
- /**
85
- * @internal
86
- */
87
- _getState(): CallState {
88
- return this._state;
89
- }
90
-
91
- setRaisedHand(raisedHand: boolean): void {
92
- if (this._state.raisedHand === raisedHand) {
93
- return;
94
- }
95
-
96
- this._state.raisedHand = raisedHand;
97
- this._notifyAndSchedule();
98
- }
99
-
100
- setSpeaking(speaking: boolean): void {
101
- if (this._state.speaking === speaking) {
102
- return;
103
- }
104
-
105
- this._state.speaking = speaking;
106
- this._notifyAndSchedule();
107
- }
108
-
109
- setJoined(joined: boolean): void {
110
- if (this._state.joined === joined) {
111
- return;
112
- }
113
-
114
- this._state.joined = joined;
115
- this._notifyAndSchedule();
116
- }
117
-
118
- setTracks(tracks: UserState['tracks']): void {
119
- this._state.tracks = { ...this._state.tracks, ...tracks };
120
- this._notifyAndSchedule();
121
- }
122
-
123
- setActivity(key: string, payload: ActivityState['payload']): void {
124
- const lamportTimestamp = LamportTimestampCrdt.increment(
125
- this._state.activities?.[key]?.lamportTimestamp ?? { id: this._deviceKey },
126
- );
127
- this._state.activities![key] = { lamportTimestamp, payload };
128
-
129
- this._notifyAndSchedule();
130
- }
131
-
132
- /**
133
- * @internal
134
- */
135
- _setIdentity(identity: Identity): void {
136
- this._identityKey = identity.identityKey.toHex();
137
- this._displayName = identity.profile?.displayName ?? generateName(identity.identityKey.toHex());
138
- }
139
-
140
- /**
141
- * @internal
142
- */
143
- _setDevice(device: Device): void {
144
- this._deviceKey = device.deviceKey.toHex();
145
- }
146
-
147
- /**
148
- * @internal
149
- */
150
- _setRoomId(roomId?: string): void {
151
- if (this._swarmCtx) {
152
- log.verbose('joined to a different room', { roomId });
153
- return;
154
- }
155
-
156
- this._state.roomId = roomId;
157
- }
158
-
159
- protected override async _open(): Promise<void> {
160
- this._sendStateTask = new DeferredTask(this._ctx, async () => {
161
- await this._sendState();
162
- });
163
-
164
- this._reconcileSwarmStateTask = new DeferredTask(this._ctx, async () => {
165
- await this._reconcileSwarmState();
166
- });
167
- }
168
-
169
- protected override async _close(): Promise<void> {
170
- this._sendStateTask = undefined;
171
- this._reconcileSwarmStateTask = undefined;
172
- }
173
-
174
- @synchronized
175
- async join(): Promise<void> {
176
- invariant(this._state.roomId);
177
- invariant(!this._swarmCtx, 'Already joined');
178
-
179
- this._swarmCtx = new Context();
180
- const topic = getTopic(this._state.roomId);
181
- log('joining swarm', { topic, peer: { identityKey: this._identityKey, peerKey: this._deviceKey } });
182
- const stream = this._networkService.subscribeSwarmState({ topic });
183
- stream.subscribe((event) => this._processSwarmEvent(event));
184
-
185
- const cleanup = () => {
186
- void stream.close();
187
- if (topic && this._identityKey && this._deviceKey) {
188
- log('leaving swarm', { topic, peer: { identityKey: this._identityKey, peerKey: this._deviceKey } });
189
- void this._networkService
190
- .leaveSwarm({
191
- topic,
192
- peer: { identityKey: this._identityKey, peerKey: this._deviceKey },
193
- })
194
- .catch((err) => log.catch(err));
195
- }
196
- window.removeEventListener('beforeunload', cleanup);
197
- };
198
- window.addEventListener('beforeunload', cleanup);
199
- this._swarmCtx.onDispose(cleanup);
200
-
201
- this._notifyAndSchedule();
202
- }
203
-
204
- @synchronized
205
- async leave(): Promise<void> {
206
- if (!this._swarmCtx) {
207
- return;
208
- }
209
-
210
- await this._swarmCtx.dispose();
211
- this._swarmCtx = undefined;
212
-
213
- this._state.users = undefined;
214
- this._state.self = undefined;
215
- }
216
-
217
- async querySwarm(roomId: string) {
218
- const topic = getTopic(roomId);
219
- const swarm = await this._networkService.querySwarm({ topic });
220
- return swarm.peers ?? [];
221
- }
222
-
223
- /**
224
- * Notify and schedule send state task.
225
- */
226
- private _notifyAndSchedule(): void {
227
- this.stateUpdated.emit(this._state);
228
- if (this._state.joined) {
229
- this._sendStateTask?.schedule();
230
- }
231
- }
232
-
233
- private async _sendState(): Promise<void> {
234
- if (!this._state.roomId || !this._identityKey || !this._deviceKey || !this._state.joined) {
235
- return;
236
- }
237
-
238
- const state: UserState = {
239
- ...this._state,
240
- id: this._deviceKey,
241
- name: this._displayName,
242
- activities: this._state.activities
243
- ? Object.fromEntries(
244
- Object.entries(this._state.activities).map(([key, activity]) => [
245
- key,
246
- buf.create(ActivitySchema, activity),
247
- ]),
248
- )
249
- : {},
250
- };
251
-
252
- await this._networkService.joinSwarm({
253
- topic: getTopic(this._state.roomId),
254
- peer: {
255
- identityKey: this._identityKey,
256
- peerKey: this._deviceKey,
257
- state: codec.encode(state),
258
- },
259
- });
260
- }
261
-
262
- private _processSwarmEvent(swarmEvent: SwarmResponse): void {
263
- if (!this._state.joined) {
264
- return;
265
- }
266
-
267
- this._lastSwarmEvent = swarmEvent;
268
- this._reconcileSwarmStateTask!.schedule();
269
- }
270
-
271
- private async _reconcileSwarmState(): Promise<void> {
272
- const swarmEvent = this._lastSwarmEvent;
273
- invariant(swarmEvent);
274
- // We include inactive peers that were disconnected abruptly and have not yet reconnected to not drop them from call.
275
- // Websocket connection could be unstable and we include graceful period for peers to reconnect.
276
- const peers = [
277
- ...(swarmEvent.peers ?? []),
278
- ...(swarmEvent.inactivePeers ?? []).filter(
279
- ({ disconnected, connectionState }) =>
280
- connectionState === ConnectionState.DISCONNECTED_ABRUPT &&
281
- disconnected &&
282
- disconnected > Date.now() - DISCONNECTED_ABRUPT_TIMEOUT,
283
- ),
284
- ].sort((peer1, peer2) => peer1.peerKey.localeCompare(peer2.peerKey));
285
- const users = peers
286
- .map((peer) => {
287
- try {
288
- return codec.decode(peer.state!);
289
- } catch (error) {
290
- log.error('error decoding peer state', { error, peer });
291
- return undefined;
292
- }
293
- })
294
- .filter(isNonNullable);
295
- this._state.users = users;
296
- this._state.self = users.find((user) => user.id === this._deviceKey);
297
- log('reconciling swarm state', { users });
298
- if (users.length === 0) {
299
- return;
300
- }
301
-
302
- const activityKeys = new Set<string>(users.flatMap((user) => Object.keys(user.activities)));
303
- [...activityKeys].forEach((key) => {
304
- const activities = users.map((user) => user.activities?.[key]).filter(isNonNullable);
305
- const lastActivity = LamportTimestampCrdt.getLastState(activities);
306
- if (
307
- lastActivity &&
308
- lastActivity.lamportTimestamp!.version! > (this._state.activities![key]?.lamportTimestamp?.version ?? 0)
309
- ) {
310
- this._state.activities![key] = lastActivity;
311
- }
312
- });
313
- this.stateUpdated.emit(this._state);
314
-
315
- // Schedule next reconcile if there are inactive peer to drop them after timeout.
316
- if (peers.some((peer) => peer.connectionState !== ConnectionState.CONNECTED)) {
317
- scheduleTaskInterval(
318
- this._ctx,
319
- async () => this._reconcileSwarmStateTask!.schedule(),
320
- Math.min(DISCONNECTED_ABRUPT_TIMEOUT / 2, 1000),
321
- );
322
- }
323
- }
324
- }
325
-
326
- type LamportTimestamp = ActivityState['lamportTimestamp'];
327
-
328
- // TODO(mykola): Factor out.
329
- class LamportTimestampCrdt {
330
- static getLastState<T extends { lamportTimestamp?: LamportTimestamp }>(states: T[]): T | undefined {
331
- const maxTimestamp = Math.max(...states.map((state) => state.lamportTimestamp?.version ?? 0));
332
- const sortedStates = states
333
- .filter(
334
- (state) =>
335
- state.lamportTimestamp && state.lamportTimestamp.version === maxTimestamp && state.lamportTimestamp.id,
336
- )
337
- .sort((a, b) => a.lamportTimestamp!.id!.localeCompare(b.lamportTimestamp!.id!));
338
- return sortedStates[0];
339
- }
340
-
341
- static increment(timestamp: LamportTimestamp): LamportTimestamp {
342
- return {
343
- ...(timestamp ?? {}),
344
- version: (timestamp?.version ?? 0) + 1,
345
- };
346
- }
347
- }
348
-
349
- // TODO(mykola): Delete once we refactor swarm to accept string as topic.
350
- const getTopic = (roomId: string): PublicKey => PublicKey.fromHex(md5Hex(roomId));
@@ -1,10 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- export * from './call-manager';
6
- export * from './call-swarm-synchronizer';
7
- export * from './media-manager';
8
- export * from './speaking-monitor';
9
- export * from './types';
10
- export * from './util';