@dxos/plugin-thread 0.8.4-main.28f8d3d → 0.8.4-main.2c6827d
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.
- package/dist/lib/browser/ChannelContainer-JI3ZRZ5S.mjs +17 -0
- package/dist/lib/browser/ChatContainer-6FVFME3R.mjs +16 -0
- package/dist/lib/browser/{app-graph-builder-AF3M7UWN.mjs → app-graph-builder-URVQHGMR.mjs} +32 -32
- package/dist/lib/browser/app-graph-builder-URVQHGMR.mjs.map +7 -0
- package/dist/lib/browser/blueprint-definition-TQ4JFMZZ.mjs +101 -0
- package/dist/lib/browser/blueprint-definition-TQ4JFMZZ.mjs.map +7 -0
- package/dist/lib/browser/{call-manager-XRRCAVLI.mjs → call-manager-4YFT4XA6.mjs} +8 -7
- package/dist/lib/{node-esm/call-manager-EI7FXRAU.mjs.map → browser/call-manager-4YFT4XA6.mjs.map} +1 -1
- package/dist/lib/browser/chunk-6LWKNZUV.mjs +377 -0
- package/dist/lib/browser/chunk-6LWKNZUV.mjs.map +7 -0
- package/dist/lib/browser/chunk-CBUNHCOE.mjs +23 -0
- package/dist/lib/browser/chunk-CBUNHCOE.mjs.map +7 -0
- package/dist/lib/browser/chunk-CFC7LEPD.mjs +18 -0
- package/dist/lib/browser/chunk-CFC7LEPD.mjs.map +7 -0
- package/dist/lib/browser/{chunk-GERVMFQW.mjs → chunk-CP7E2HRE.mjs} +2 -2
- package/dist/lib/browser/chunk-CP7E2HRE.mjs.map +7 -0
- package/dist/lib/browser/{chunk-ZJ7QBXK6.mjs → chunk-F36NHPJG.mjs} +47 -42
- package/dist/lib/browser/chunk-F36NHPJG.mjs.map +7 -0
- package/dist/lib/browser/{chunk-JGKMMI65.mjs → chunk-ISCHODBV.mjs} +54 -4
- package/dist/lib/browser/chunk-ISCHODBV.mjs.map +7 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/browser/{chunk-X5PIP5YR.mjs → chunk-KOBXMDCI.mjs} +74 -41
- package/dist/lib/browser/chunk-KOBXMDCI.mjs.map +7 -0
- package/dist/lib/browser/chunk-QM34EZQK.mjs +20 -0
- package/dist/lib/browser/chunk-QM34EZQK.mjs.map +7 -0
- package/dist/lib/browser/chunk-R5UOPOO7.mjs +142 -0
- package/dist/lib/browser/chunk-R5UOPOO7.mjs.map +7 -0
- package/dist/lib/browser/chunk-VIRD2QSK.mjs +611 -0
- package/dist/lib/browser/chunk-VIRD2QSK.mjs.map +7 -0
- package/dist/lib/browser/{chunk-TUFWPOVS.mjs → chunk-ZCW3NSDZ.mjs} +256 -161
- package/dist/lib/browser/chunk-ZCW3NSDZ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +48 -38
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-DCY4P4OX.mjs → intent-resolver-YR6W4CRP.mjs} +33 -51
- package/dist/lib/browser/intent-resolver-YR6W4CRP.mjs.map +7 -0
- package/dist/lib/browser/{markdown-WZSXCEZJ.mjs → markdown-GSOBOXA7.mjs} +26 -24
- package/dist/lib/browser/markdown-GSOBOXA7.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/react-root-RAWRPF7Z.mjs +29 -0
- package/dist/lib/browser/react-root-RAWRPF7Z.mjs.map +7 -0
- package/dist/lib/browser/{react-surface-PYAMIADB.mjs → react-surface-GOEFSXQ6.mjs} +38 -36
- package/dist/lib/browser/react-surface-GOEFSXQ6.mjs.map +7 -0
- package/dist/lib/browser/{settings-AC6YSASL.mjs → settings-JN2HHORY.mjs} +6 -5
- package/dist/lib/{node-esm/settings-N52O7MLS.mjs.map → browser/settings-JN2HHORY.mjs.map} +1 -1
- package/dist/lib/browser/{state-2T4KDWBX.mjs → state-UYPLBGZJ.mjs} +6 -5
- package/dist/lib/{node-esm/state-62TQKQVB.mjs.map → browser/state-UYPLBGZJ.mjs.map} +1 -1
- package/dist/lib/browser/types/index.mjs +7 -10
- package/dist/lib/node-esm/ChannelContainer-RQY4PR4F.mjs +18 -0
- package/dist/lib/node-esm/ChatContainer-KWNON7EN.mjs +17 -0
- package/dist/lib/node-esm/ChatContainer-KWNON7EN.mjs.map +7 -0
- package/dist/lib/node-esm/{app-graph-builder-OLSJVCWY.mjs → app-graph-builder-2IH5RPR7.mjs} +32 -32
- package/dist/lib/node-esm/app-graph-builder-2IH5RPR7.mjs.map +7 -0
- package/dist/lib/node-esm/blueprint-definition-TSX5HHW7.mjs +102 -0
- package/dist/lib/node-esm/blueprint-definition-TSX5HHW7.mjs.map +7 -0
- package/dist/lib/node-esm/{call-manager-EI7FXRAU.mjs → call-manager-UMUXEYH5.mjs} +8 -7
- package/dist/lib/{browser/call-manager-XRRCAVLI.mjs.map → node-esm/call-manager-UMUXEYH5.mjs.map} +1 -1
- package/dist/lib/node-esm/chunk-2AEIN5MI.mjs +22 -0
- package/dist/lib/node-esm/chunk-2AEIN5MI.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-4TME3BR4.mjs → chunk-7KZWZS2U.mjs} +256 -161
- package/dist/lib/node-esm/chunk-7KZWZS2U.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-57XR3LEF.mjs → chunk-ABUFOZVX.mjs} +2 -2
- package/dist/lib/node-esm/chunk-ABUFOZVX.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-I3O6NXMN.mjs +25 -0
- package/dist/lib/node-esm/chunk-I3O6NXMN.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-MEIWWPR2.mjs +143 -0
- package/dist/lib/node-esm/chunk-MEIWWPR2.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-SED3O2XO.mjs → chunk-PZH2EDU5.mjs} +74 -41
- package/dist/lib/node-esm/chunk-PZH2EDU5.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-QFCIKJOD.mjs +612 -0
- package/dist/lib/node-esm/chunk-QFCIKJOD.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-RT6NRL2I.mjs +19 -0
- package/dist/lib/node-esm/chunk-RT6NRL2I.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-QBHKLWGR.mjs → chunk-VBI32FGI.mjs} +54 -4
- package/dist/lib/node-esm/chunk-VBI32FGI.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-YIDU3DXK.mjs → chunk-Y3F2SGNH.mjs} +47 -42
- package/dist/lib/node-esm/chunk-Y3F2SGNH.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-Z4GUSLWL.mjs +378 -0
- package/dist/lib/node-esm/chunk-Z4GUSLWL.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +48 -38
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/{intent-resolver-QGTPU6QB.mjs → intent-resolver-SJFABEE7.mjs} +33 -51
- package/dist/lib/node-esm/intent-resolver-SJFABEE7.mjs.map +7 -0
- package/dist/lib/node-esm/{markdown-3MZXUGUA.mjs → markdown-GG5566TL.mjs} +26 -24
- package/dist/lib/node-esm/markdown-GG5566TL.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/react-root-K5OGECUS.mjs +30 -0
- package/dist/lib/node-esm/react-root-K5OGECUS.mjs.map +7 -0
- package/dist/lib/node-esm/{react-surface-UJFCSFNO.mjs → react-surface-5QDQD7MN.mjs} +38 -36
- package/dist/lib/node-esm/react-surface-5QDQD7MN.mjs.map +7 -0
- package/dist/lib/node-esm/{settings-N52O7MLS.mjs → settings-VSPM3BIM.mjs} +6 -5
- package/dist/lib/{browser/settings-AC6YSASL.mjs.map → node-esm/settings-VSPM3BIM.mjs.map} +1 -1
- package/dist/lib/node-esm/{state-62TQKQVB.mjs → state-XNWOLBNE.mjs} +6 -5
- package/dist/lib/{browser/state-2T4KDWBX.mjs.map → node-esm/state-XNWOLBNE.mjs.map} +1 -1
- package/dist/lib/node-esm/types/index.mjs +7 -10
- package/dist/types/src/ThreadPlugin.d.ts +1 -1
- package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
- package/dist/types/src/calls/media-manager.d.ts +1 -1
- package/dist/types/src/calls/media-manager.d.ts.map +1 -1
- package/dist/types/src/calls/types.d.ts.map +1 -1
- package/dist/types/src/calls/util/calls-service.d.ts +3 -1
- package/dist/types/src/calls/util/calls-service.d.ts.map +1 -1
- package/dist/types/src/calls/util/stub-media-streams.d.ts.map +1 -1
- package/dist/types/src/calls-service.stories.d.ts +10 -9
- package/dist/types/src/calls-service.stories.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/blueprint-definition.d.ts +5 -0
- package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -0
- package/dist/types/src/capabilities/call-manager.d.ts +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts +2 -2
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +11 -10
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/markdown.d.ts +1 -1
- package/dist/types/src/capabilities/markdown.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-root.d.ts +2 -2
- package/dist/types/src/capabilities/react-surface.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/settings.d.ts +1 -1
- package/dist/types/src/capabilities/state.d.ts +2 -2
- package/dist/types/src/components/Call/Toolbar.d.ts +2 -2
- package/dist/types/src/components/Call/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/CallDebugPanel.d.ts +7 -0
- package/dist/types/src/components/CallDebugPanel.d.ts.map +1 -1
- package/dist/types/src/components/ChannelContainer.d.ts +2 -2
- package/dist/types/src/components/ChannelContainer.d.ts.map +1 -1
- package/dist/types/src/components/ChannelContainer.stories.d.ts +155 -5
- package/dist/types/src/components/ChannelContainer.stories.d.ts.map +1 -1
- package/dist/types/src/components/Chat.stories.d.ts +158 -5
- package/dist/types/src/components/Chat.stories.d.ts.map +1 -1
- package/dist/types/src/components/ChatContainer.d.ts +6 -5
- package/dist/types/src/components/ChatContainer.d.ts.map +1 -1
- package/dist/types/src/components/Comments.stories.d.ts +156 -4
- package/dist/types/src/components/Comments.stories.d.ts.map +1 -1
- package/dist/types/src/components/CommentsContainer.d.ts +2 -2
- package/dist/types/src/components/CommentsContainer.d.ts.map +1 -1
- package/dist/types/src/components/CommentsThreadContainer.d.ts +9 -9
- package/dist/types/src/components/CommentsThreadContainer.d.ts.map +1 -1
- package/dist/types/src/components/Media/VideoObject.d.ts +2 -2
- package/dist/types/src/components/Media/VideoObject.d.ts.map +1 -1
- package/dist/types/src/components/Media/VideoObject.stories.d.ts +18 -4
- package/dist/types/src/components/Media/VideoObject.stories.d.ts.map +1 -1
- package/dist/types/src/components/MessageContainer.d.ts +6 -3
- package/dist/types/src/components/MessageContainer.d.ts.map +1 -1
- package/dist/types/src/components/Participant/Participant.d.ts.map +1 -1
- package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts +155 -3
- package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts.map +1 -1
- package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts +157 -4
- package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts.map +1 -1
- package/dist/types/src/components/ResponsiveGrid/ResponsiveGridItem.d.ts.map +1 -1
- package/dist/types/src/components/ThreadCompanion.d.ts +5 -0
- package/dist/types/src/components/ThreadCompanion.d.ts.map +1 -0
- package/dist/types/src/components/ThreadSettings.d.ts +1 -1
- package/dist/types/src/components/ThreadSettings.d.ts.map +1 -1
- package/dist/types/src/components/command-extension.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +3 -3
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +3 -2
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/extensions/threads.d.ts.map +1 -1
- package/dist/types/src/functions/create-proposals.d.ts +6 -0
- package/dist/types/src/functions/create-proposals.d.ts.map +1 -0
- package/dist/types/src/functions/index.d.ts +2 -0
- package/dist/types/src/functions/index.d.ts.map +1 -0
- package/dist/types/src/hooks/analytics.d.ts +2 -2
- package/dist/types/src/hooks/analytics.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useBlackCanvasStreamTrack.d.ts +2 -0
- package/dist/types/src/hooks/useBlackCanvasStreamTrack.d.ts.map +1 -0
- package/dist/types/src/hooks/useVideoStreamTrack.d.ts +1 -1
- package/dist/types/src/hooks/useVideoStreamTrack.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +1 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/testing/stories.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +75 -7
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Channel.d.ts +16 -0
- package/dist/types/src/types/Channel.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +1 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +206 -210
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +65 -59
- package/src/ThreadPlugin.tsx +139 -125
- package/src/calls/call-manager.ts +1 -1
- package/src/calls/media-manager.ts +64 -35
- package/src/calls/types.ts +7 -3
- package/src/calls/util/calls-service.ts +61 -11
- package/src/calls/util/stub-media-streams.ts +62 -5
- package/src/calls-service.stories.tsx +76 -63
- package/src/capabilities/app-graph-builder.ts +43 -30
- package/src/capabilities/blueprint-definition.ts +38 -0
- package/src/capabilities/capabilities.ts +7 -7
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/intent-resolver.ts +23 -30
- package/src/capabilities/markdown.ts +5 -3
- package/src/capabilities/react-root.tsx +2 -2
- package/src/capabilities/react-surface.tsx +25 -23
- package/src/components/Call/Call.tsx +1 -1
- package/src/components/Call/Toolbar.tsx +9 -9
- package/src/components/CallDebugPanel.tsx +112 -55
- package/src/components/CallSidebar.tsx +1 -1
- package/src/components/ChannelContainer.stories.tsx +13 -13
- package/src/components/ChannelContainer.tsx +19 -15
- package/src/components/Chat.stories.tsx +30 -34
- package/src/components/ChatContainer.tsx +32 -21
- package/src/components/Comments.stories.tsx +36 -39
- package/src/components/CommentsContainer.tsx +5 -7
- package/src/components/CommentsThreadContainer.tsx +38 -33
- package/src/components/Lobby/Lobby.tsx +1 -1
- package/src/components/Media/VideoObject.stories.tsx +35 -28
- package/src/components/Media/VideoObject.tsx +1 -1
- package/src/components/MessageContainer.tsx +45 -12
- package/src/components/Participant/Participant.tsx +14 -8
- package/src/components/ResponsiveGrid/ResponsiveContainer.stories.tsx +5 -6
- package/src/components/ResponsiveGrid/ResponsiveContainer.tsx +2 -2
- package/src/components/ResponsiveGrid/ResponsiveGrid.stories.tsx +42 -41
- package/src/components/ResponsiveGrid/ResponsiveGrid.tsx +5 -5
- package/src/components/ResponsiveGrid/ResponsiveGridItem.tsx +5 -2
- package/src/components/{ThreadComplementary.tsx → ThreadCompanion.tsx} +72 -35
- package/src/components/ThreadSettings.tsx +6 -7
- package/src/components/command-extension.ts +4 -1
- package/src/components/index.ts +4 -4
- package/src/components/testing.ts +26 -6
- package/src/extensions/threads.ts +26 -17
- package/src/functions/create-proposals.ts +56 -0
- package/src/functions/index.ts +5 -0
- package/src/hooks/analytics.ts +4 -7
- package/src/hooks/index.ts +3 -1
- package/src/hooks/useBlackCanvasStreamTrack.tsx +27 -0
- package/src/hooks/useVideoStreamTrack.tsx +6 -3
- package/src/meta.ts +9 -5
- package/src/testing/stories.ts +3 -6
- package/src/translations.ts +7 -4
- package/src/types/Channel.ts +26 -0
- package/src/types/index.ts +1 -1
- package/src/types/types.ts +27 -28
- package/src/typings/peermetrics-webrtc-stats.d.ts +17 -1
- package/src/util.ts +1 -1
- package/dist/lib/browser/ChannelContainer-O2SFQJU7.mjs +0 -16
- package/dist/lib/browser/ChatContainer-PVT3DUZJ.mjs +0 -15
- package/dist/lib/browser/app-graph-builder-AF3M7UWN.mjs.map +0 -7
- package/dist/lib/browser/chunk-2CWJBXBH.mjs +0 -21
- package/dist/lib/browser/chunk-2CWJBXBH.mjs.map +0 -7
- package/dist/lib/browser/chunk-4APCDRSH.mjs +0 -18
- package/dist/lib/browser/chunk-4APCDRSH.mjs.map +0 -7
- package/dist/lib/browser/chunk-DW7JD64V.mjs +0 -137
- package/dist/lib/browser/chunk-DW7JD64V.mjs.map +0 -7
- package/dist/lib/browser/chunk-EV4JWI7L.mjs +0 -17
- package/dist/lib/browser/chunk-EV4JWI7L.mjs.map +0 -7
- package/dist/lib/browser/chunk-FY4ZRD5X.mjs +0 -367
- package/dist/lib/browser/chunk-FY4ZRD5X.mjs.map +0 -7
- package/dist/lib/browser/chunk-GERVMFQW.mjs.map +0 -7
- package/dist/lib/browser/chunk-J3JO5NWO.mjs +0 -477
- package/dist/lib/browser/chunk-J3JO5NWO.mjs.map +0 -7
- package/dist/lib/browser/chunk-JGKMMI65.mjs.map +0 -7
- package/dist/lib/browser/chunk-TUFWPOVS.mjs.map +0 -7
- package/dist/lib/browser/chunk-X5PIP5YR.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZJ7QBXK6.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-DCY4P4OX.mjs.map +0 -7
- package/dist/lib/browser/markdown-WZSXCEZJ.mjs.map +0 -7
- package/dist/lib/browser/react-root-QXPALOUQ.mjs +0 -28
- package/dist/lib/browser/react-root-QXPALOUQ.mjs.map +0 -7
- package/dist/lib/browser/react-surface-PYAMIADB.mjs.map +0 -7
- package/dist/lib/node-esm/ChannelContainer-B2ZGAE4P.mjs +0 -17
- package/dist/lib/node-esm/ChatContainer-2CT4PJ7I.mjs +0 -16
- package/dist/lib/node-esm/app-graph-builder-OLSJVCWY.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-4TME3BR4.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-57XR3LEF.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-6CRHHOST.mjs +0 -23
- package/dist/lib/node-esm/chunk-6CRHHOST.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-BF4UKS55.mjs +0 -368
- package/dist/lib/node-esm/chunk-BF4UKS55.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-GRLRWTRU.mjs +0 -19
- package/dist/lib/node-esm/chunk-GRLRWTRU.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-PYTVBN5J.mjs +0 -19
- package/dist/lib/node-esm/chunk-PYTVBN5J.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-QBHKLWGR.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-SED3O2XO.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-VNG6M2IY.mjs +0 -478
- package/dist/lib/node-esm/chunk-VNG6M2IY.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XVKWHTH4.mjs +0 -138
- package/dist/lib/node-esm/chunk-XVKWHTH4.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-YIDU3DXK.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-QGTPU6QB.mjs.map +0 -7
- package/dist/lib/node-esm/markdown-3MZXUGUA.mjs.map +0 -7
- package/dist/lib/node-esm/react-root-7ZFJYVUZ.mjs +0 -29
- package/dist/lib/node-esm/react-root-7ZFJYVUZ.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-UJFCSFNO.mjs.map +0 -7
- package/dist/types/src/components/ThreadComplementary.d.ts +0 -5
- package/dist/types/src/components/ThreadComplementary.d.ts.map +0 -1
- package/dist/types/src/types/schema.d.ts +0 -164
- package/dist/types/src/types/schema.d.ts.map +0 -1
- package/src/types/schema.ts +0 -33
- /package/dist/lib/browser/{ChannelContainer-O2SFQJU7.mjs.map → ChannelContainer-JI3ZRZ5S.mjs.map} +0 -0
- /package/dist/lib/browser/{ChatContainer-PVT3DUZJ.mjs.map → ChatContainer-6FVFME3R.mjs.map} +0 -0
- /package/dist/lib/{node-esm/ChannelContainer-B2ZGAE4P.mjs.map → browser/chunk-J5LGTIGS.mjs.map} +0 -0
- /package/dist/lib/node-esm/{ChatContainer-2CT4PJ7I.mjs.map → ChannelContainer-RQY4PR4F.mjs.map} +0 -0
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ThreadCapabilities
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-CFC7LEPD.mjs";
|
|
4
4
|
import {
|
|
5
5
|
ChatContainer_default
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6LWKNZUV.mjs";
|
|
7
7
|
import {
|
|
8
8
|
useDebugMode
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KOBXMDCI.mjs";
|
|
10
10
|
import {
|
|
11
11
|
meta
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-QM34EZQK.mjs";
|
|
13
13
|
|
|
14
14
|
// src/components/ChannelContainer.tsx
|
|
15
15
|
import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
|
|
16
|
-
import {
|
|
16
|
+
import { Atom } from "@effect-atom/atom-react";
|
|
17
17
|
import React10, { useCallback as useCallback2, useEffect as useEffect6, useMemo as useMemo4, useState as useState4 } from "react";
|
|
18
|
-
import { useCapabilities, useCapability as useCapability4 } from "@dxos/app-framework";
|
|
18
|
+
import { useCapabilities, useCapability as useCapability4 } from "@dxos/app-framework/react";
|
|
19
19
|
import { Context } from "@dxos/context";
|
|
20
20
|
import { failUndefined } from "@dxos/debug";
|
|
21
|
+
import { Obj as Obj2 } from "@dxos/echo";
|
|
21
22
|
import { log } from "@dxos/log";
|
|
22
23
|
import { useClient } from "@dxos/react-client";
|
|
23
|
-
import {
|
|
24
|
+
import { getSpace } from "@dxos/react-client/echo";
|
|
24
25
|
import { useIdentity } from "@dxos/react-client/halo";
|
|
25
26
|
import { ElevationProvider, Input, useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
26
27
|
import { ControlGroup, ControlGroupButton, ControlItemInput } from "@dxos/react-ui-form";
|
|
@@ -31,7 +32,7 @@ import { StackItem } from "@dxos/react-ui-stack";
|
|
|
31
32
|
// src/components/Call/Call.tsx
|
|
32
33
|
import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
|
|
33
34
|
import React9 from "react";
|
|
34
|
-
import { useCapability as useCapability3 } from "@dxos/app-framework";
|
|
35
|
+
import { useCapability as useCapability3 } from "@dxos/app-framework/react";
|
|
35
36
|
|
|
36
37
|
// src/components/Media/AudioStream.tsx
|
|
37
38
|
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
@@ -109,7 +110,7 @@ var VideoObject = /* @__PURE__ */ memo(/* @__PURE__ */ forwardRef(({ videoStream
|
|
|
109
110
|
internalRef.current
|
|
110
111
|
]);
|
|
111
112
|
return /* @__PURE__ */ React2.createElement("video", {
|
|
112
|
-
className: mx("
|
|
113
|
+
className: mx("is-full aspect-video", flip && "scale-x-[-1]", contain ? "object-contain" : "object-cover", classNames),
|
|
113
114
|
ref: (v) => {
|
|
114
115
|
internalRef.current = v;
|
|
115
116
|
if (ref === null) {
|
|
@@ -132,7 +133,7 @@ VideoObject.displayName = "VideoObject";
|
|
|
132
133
|
// src/components/Participant/Participant.tsx
|
|
133
134
|
import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
|
|
134
135
|
import React6, { memo as memo2, useMemo as useMemo2 } from "react";
|
|
135
|
-
import { useCapability } from "@dxos/app-framework";
|
|
136
|
+
import { useCapability } from "@dxos/app-framework/react";
|
|
136
137
|
|
|
137
138
|
// src/components/ResponsiveGrid/ResponsiveContainer.tsx
|
|
138
139
|
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
@@ -145,13 +146,13 @@ var ResponsiveContainer = ({ children }) => {
|
|
|
145
146
|
// Outer container that takes full size of parent.
|
|
146
147
|
/* @__PURE__ */ React3.createElement("div", {
|
|
147
148
|
role: "none",
|
|
148
|
-
className: "relative flex
|
|
149
|
+
className: "relative flex is-full bs-full"
|
|
149
150
|
}, /* @__PURE__ */ React3.createElement("div", {
|
|
150
151
|
role: "none",
|
|
151
152
|
className: "absolute inset-0 flex justify-center items-center"
|
|
152
153
|
}, /* @__PURE__ */ React3.createElement("div", {
|
|
153
154
|
role: "none",
|
|
154
|
-
className: mx2("max-
|
|
155
|
+
className: mx2("max-bs-full max-is-full is-auto bs-auto aspect-video")
|
|
155
156
|
}, children)))
|
|
156
157
|
);
|
|
157
158
|
} finally {
|
|
@@ -169,7 +170,7 @@ var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/components
|
|
|
169
170
|
var ASPECT_RATIO = 16 / 9;
|
|
170
171
|
var MIN_GALLERY_HEIGHT = 250;
|
|
171
172
|
var DEFAULT_GAP = 8;
|
|
172
|
-
var maxImageSize = "
|
|
173
|
+
var maxImageSize = "is-[2560px] bs-[1440px]";
|
|
173
174
|
var defaultGetId = (item) => item.id;
|
|
174
175
|
var ResponsiveGrid = ({ classNames, Cell, gap = DEFAULT_GAP, getId: getId2 = defaultGetId, items, pinned, autoHideGallery = false, debug, onPinnedChange }) => {
|
|
175
176
|
var _effect = _useSignals4();
|
|
@@ -261,11 +262,11 @@ var ResponsiveGrid = ({ classNames, Cell, gap = DEFAULT_GAP, getId: getId2 = def
|
|
|
261
262
|
]);
|
|
262
263
|
return /* @__PURE__ */ React4.createElement("div", {
|
|
263
264
|
ref: containerRef,
|
|
264
|
-
className: mx3("relative
|
|
265
|
+
className: mx3("relative is-full bs-full", classNames)
|
|
265
266
|
}, /* @__PURE__ */ React4.createElement("div", {
|
|
266
267
|
className: "absolute inset-0 flex flex-col grow gap-2"
|
|
267
268
|
}, pinnedItem && /* @__PURE__ */ React4.createElement("div", {
|
|
268
|
-
className: mx3("flex grow-[2] shrink overflow-hidden justify-center items-center", hideGallery && "
|
|
269
|
+
className: mx3("flex grow-[2] shrink overflow-hidden justify-center items-center", hideGallery && "bs-full"),
|
|
269
270
|
style: hideGallery ? {} : {
|
|
270
271
|
height: dividerHeight
|
|
271
272
|
}
|
|
@@ -282,7 +283,7 @@ var ResponsiveGrid = ({ classNames, Cell, gap = DEFAULT_GAP, getId: getId2 = def
|
|
|
282
283
|
style: {
|
|
283
284
|
width: cellWidth
|
|
284
285
|
},
|
|
285
|
-
className: "flex
|
|
286
|
+
className: "flex bs-full"
|
|
286
287
|
}, /* @__PURE__ */ React4.createElement(SoloItem, {
|
|
287
288
|
id: getId2(mainItems[0]),
|
|
288
289
|
debug
|
|
@@ -296,7 +297,7 @@ var ResponsiveGrid = ({ classNames, Cell, gap = DEFAULT_GAP, getId: getId2 = def
|
|
|
296
297
|
}, mainItems.map((item) => /* @__PURE__ */ React4.createElement("div", {
|
|
297
298
|
key: getId2(item),
|
|
298
299
|
"data-grid-item": getId2(item),
|
|
299
|
-
className: mx3("aspect-video max-
|
|
300
|
+
className: mx3("aspect-video max-bs-full max-is-full is-auto bs-auto", debug && "border border-primary-500")
|
|
300
301
|
}))))), /* @__PURE__ */ React4.createElement("div", {
|
|
301
302
|
className: mx3(debug && "opacity-10")
|
|
302
303
|
}, bounds.map(([item, bounds2]) => /* @__PURE__ */ React4.createElement(Cell, {
|
|
@@ -424,7 +425,7 @@ var ResponsiveGridItem = ({ children, classNames, item, style, name, self, pinne
|
|
|
424
425
|
speaking
|
|
425
426
|
]);
|
|
426
427
|
return /* @__PURE__ */ React5.createElement("div", {
|
|
427
|
-
className: mx4("relative
|
|
428
|
+
className: mx4("relative is-full bs-full group", "rounded-md outline outline-2 outline-neutral-900 transition-[outline-color] duration-500", speakingIndicator ? "outline-green-500" : !video && "outline-separator", classNames),
|
|
428
429
|
style
|
|
429
430
|
}, children, onClick && /* @__PURE__ */ React5.createElement("div", {
|
|
430
431
|
className: "z-10 absolute top-1 right-1 flex"
|
|
@@ -441,7 +442,7 @@ var ResponsiveGridItem = ({ children, classNames, item, style, name, self, pinne
|
|
|
441
442
|
icon: "ph--broadcast--regular",
|
|
442
443
|
size: pinned ? 5 : 4
|
|
443
444
|
}), /* @__PURE__ */ React5.createElement("div", {
|
|
444
|
-
className: mx4("bg-neutral-800 text-neutral-100
|
|
445
|
+
className: mx4("bg-neutral-800 text-neutral-100 plb-0.5 truncate rounded", pinned ? "pli-2" : "pli-1 text-xs")
|
|
445
446
|
}, name)), /* @__PURE__ */ React5.createElement("div", {
|
|
446
447
|
className: "z-10 absolute bottom-1 left-1 flex"
|
|
447
448
|
}, speaking && /* @__PURE__ */ React5.createElement(Waveform, {
|
|
@@ -467,12 +468,14 @@ var Participant = /* @__PURE__ */ memo2(({ item: user, debug, ...props }) => {
|
|
|
467
468
|
const call = useCapability(ThreadCapabilities.CallManager);
|
|
468
469
|
const isSelf = call.self.id !== void 0 && user.id !== void 0 && user.id.startsWith(call.self.id);
|
|
469
470
|
const isScreenshare = user.id?.endsWith(SCREENSHARE_SUFFIX);
|
|
470
|
-
const pulledVideoStream = call.getVideoStream(
|
|
471
|
+
const pulledVideoStream = !isSelf && isScreenshare && user.tracks?.screenshareEnabled ? call.getVideoStream(user.tracks?.screenshare) : !isSelf && !isScreenshare && user.tracks?.videoEnabled ? call.getVideoStream(user.tracks?.video) : void 0;
|
|
471
472
|
const videoStream = useMemo2(() => {
|
|
472
|
-
if (isSelf
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
473
|
+
if (isSelf) {
|
|
474
|
+
if (isScreenshare) {
|
|
475
|
+
return call.media.screenshareVideoStream;
|
|
476
|
+
} else if (!isScreenshare) {
|
|
477
|
+
return call.media.videoStream;
|
|
478
|
+
}
|
|
476
479
|
} else if (!isSelf) {
|
|
477
480
|
return pulledVideoStream;
|
|
478
481
|
}
|
|
@@ -583,10 +586,10 @@ var ParticipantGrid = ({ classNames, self, users, fullscreen, debug }) => {
|
|
|
583
586
|
// src/components/Call/Toolbar.tsx
|
|
584
587
|
import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
|
|
585
588
|
import React8 from "react";
|
|
586
|
-
import { useAppGraph, useCapability as useCapability2 } from "@dxos/app-framework";
|
|
589
|
+
import { useAppGraph, useCapability as useCapability2 } from "@dxos/app-framework/react";
|
|
590
|
+
import { Obj } from "@dxos/echo";
|
|
587
591
|
import { useActions, useNode } from "@dxos/plugin-graph";
|
|
588
|
-
import {
|
|
589
|
-
import { Icon as Icon2, IconButton as IconButton2, Toolbar as NativeToolbar, toLocalizedString, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
592
|
+
import { Icon as Icon2, IconButton as IconButton2, Toolbar as NaturalToolbar, toLocalizedString, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
590
593
|
import { groupHoverControlItemWithTransition as groupHoverControlItemWithTransition2, mx as mx5 } from "@dxos/react-ui-theme";
|
|
591
594
|
var Toolbar = ({ classNames, channel, participants, autoHideControls = true, onJoin, onLeave }) => {
|
|
592
595
|
var _effect = _useSignals8();
|
|
@@ -594,13 +597,13 @@ var Toolbar = ({ classNames, channel, participants, autoHideControls = true, onJ
|
|
|
594
597
|
const { t } = useTranslation2(meta.id);
|
|
595
598
|
const { graph } = useAppGraph();
|
|
596
599
|
const call = useCapability2(ThreadCapabilities.CallManager);
|
|
597
|
-
const node = useNode(graph, channel &&
|
|
600
|
+
const node = useNode(graph, channel && Obj.getDXN(channel).toString());
|
|
598
601
|
const actions = useActions(graph, node?.id).filter((action) => action.properties.disposition === "toolbar");
|
|
599
602
|
const isScreensharing = call.media.screenshareTrack !== void 0;
|
|
600
603
|
const canSharescreen = typeof navigator.mediaDevices !== "undefined" && navigator.mediaDevices.getDisplayMedia !== void 0;
|
|
601
604
|
return /* @__PURE__ */ React8.createElement("div", {
|
|
602
605
|
className: mx5("z-20 flex justify-center m-8", autoHideControls && groupHoverControlItemWithTransition2)
|
|
603
|
-
}, /* @__PURE__ */ React8.createElement(
|
|
606
|
+
}, /* @__PURE__ */ React8.createElement(NaturalToolbar.Root, {
|
|
604
607
|
classNames: [
|
|
605
608
|
"p-2 bg-modalSurface rounded-md shadow-md",
|
|
606
609
|
classNames
|
|
@@ -642,7 +645,7 @@ var Toolbar = ({ classNames, channel, participants, autoHideControls = true, onJ
|
|
|
642
645
|
}, /* @__PURE__ */ React8.createElement(Icon2, {
|
|
643
646
|
icon: "ph--users--regular",
|
|
644
647
|
size: 4
|
|
645
|
-
}), /* @__PURE__ */ React8.createElement("div", null, participants)) || /* @__PURE__ */ React8.createElement(
|
|
648
|
+
}), /* @__PURE__ */ React8.createElement("div", null, participants)) || /* @__PURE__ */ React8.createElement(NaturalToolbar.Separator, {
|
|
646
649
|
variant: "gap"
|
|
647
650
|
}), call.joined && /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(ToggleButton, {
|
|
648
651
|
disabled: !canSharescreen,
|
|
@@ -792,7 +795,8 @@ var ChannelContainer = ({ channel, roomId: _roomId, role, fullscreen }) => {
|
|
|
792
795
|
try {
|
|
793
796
|
const space = getSpace(channel);
|
|
794
797
|
const callManager = useCapability4(ThreadCapabilities.CallManager);
|
|
795
|
-
const
|
|
798
|
+
const attendableId = channel ? Obj2.getDXN(channel).toString() : void 0;
|
|
799
|
+
const roomId = _roomId ?? attendableId ?? failUndefined();
|
|
796
800
|
const identity = useIdentity();
|
|
797
801
|
const isNamed = !!identity?.profile?.displayName;
|
|
798
802
|
const joinSound = useSoundEffect("JoinCall");
|
|
@@ -801,7 +805,7 @@ var ChannelContainer = ({ channel, roomId: _roomId, role, fullscreen }) => {
|
|
|
801
805
|
useEffect6(() => {
|
|
802
806
|
const ctx = new Context(void 0, {
|
|
803
807
|
F: __dxlog_file2,
|
|
804
|
-
L:
|
|
808
|
+
L: 53
|
|
805
809
|
});
|
|
806
810
|
callManager.left.on(ctx, (roomId2) => {
|
|
807
811
|
extensions.forEach((extension) => {
|
|
@@ -843,7 +847,7 @@ var ChannelContainer = ({ channel, roomId: _roomId, role, fullscreen }) => {
|
|
|
843
847
|
} catch (err) {
|
|
844
848
|
log.catch(err, void 0, {
|
|
845
849
|
F: __dxlog_file2,
|
|
846
|
-
L:
|
|
850
|
+
L: 97,
|
|
847
851
|
S: void 0,
|
|
848
852
|
C: (f, a) => f(...a)
|
|
849
853
|
});
|
|
@@ -859,7 +863,7 @@ var ChannelContainer = ({ channel, roomId: _roomId, role, fullscreen }) => {
|
|
|
859
863
|
} catch (err) {
|
|
860
864
|
log.catch(err, void 0, {
|
|
861
865
|
F: __dxlog_file2,
|
|
862
|
-
L:
|
|
866
|
+
L: 109,
|
|
863
867
|
S: void 0,
|
|
864
868
|
C: (f, a) => f(...a)
|
|
865
869
|
});
|
|
@@ -875,20 +879,21 @@ var ChannelContainer = ({ channel, roomId: _roomId, role, fullscreen }) => {
|
|
|
875
879
|
]);
|
|
876
880
|
const isJoined = callManager.joined && callManager.roomId === roomId;
|
|
877
881
|
return /* @__PURE__ */ React10.createElement(StackItem.Content, {
|
|
878
|
-
|
|
879
|
-
|
|
882
|
+
classNames: isJoined && "bs-full",
|
|
883
|
+
toolbar: !isJoined
|
|
880
884
|
}, isJoined && !isNamed && /* @__PURE__ */ React10.createElement(DisplayNameMissing, null), isJoined && isNamed && /* @__PURE__ */ React10.createElement(Call.Root, null, /* @__PURE__ */ React10.createElement(Call.Grid, {
|
|
881
885
|
fullscreen
|
|
882
886
|
}), /* @__PURE__ */ React10.createElement(Call.Toolbar, {
|
|
883
887
|
channel,
|
|
884
888
|
onLeave: handleLeave
|
|
885
889
|
})), !isJoined && channel && channel.defaultThread.target && space && /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(ChannelToolbar, {
|
|
886
|
-
attendableId
|
|
890
|
+
attendableId,
|
|
887
891
|
role,
|
|
888
892
|
onJoinCall: handleJoin
|
|
889
893
|
}), /* @__PURE__ */ React10.createElement(ChatContainer_default, {
|
|
890
894
|
space,
|
|
891
|
-
thread: channel.defaultThread.target
|
|
895
|
+
thread: channel.defaultThread.target,
|
|
896
|
+
classNames: "container-max-width"
|
|
892
897
|
})));
|
|
893
898
|
} finally {
|
|
894
899
|
_effect.f();
|
|
@@ -927,7 +932,7 @@ var DisplayNameMissing = () => {
|
|
|
927
932
|
}
|
|
928
933
|
};
|
|
929
934
|
var useChannelToolbarActions = (onJoinCall) => {
|
|
930
|
-
const creator = useMemo4(() =>
|
|
935
|
+
const creator = useMemo4(() => Atom.make(() => {
|
|
931
936
|
return {
|
|
932
937
|
nodes: [
|
|
933
938
|
createMenuItemGroup("root", {
|
|
@@ -959,7 +964,7 @@ var useChannelToolbarActions = (onJoinCall) => {
|
|
|
959
964
|
}), []);
|
|
960
965
|
return useMenuActions(creator);
|
|
961
966
|
};
|
|
962
|
-
var ChannelToolbar = ({ attendableId, role, onJoinCall
|
|
967
|
+
var ChannelToolbar = ({ attendableId, role, onJoinCall }) => {
|
|
963
968
|
var _effect = _useSignals10();
|
|
964
969
|
try {
|
|
965
970
|
const menuProps = useChannelToolbarActions(onJoinCall);
|
|
@@ -969,7 +974,7 @@ var ChannelToolbar = ({ attendableId, role, onJoinCall, classNames }) => {
|
|
|
969
974
|
...menuProps,
|
|
970
975
|
attendableId
|
|
971
976
|
}, /* @__PURE__ */ React10.createElement(ToolbarMenu, {
|
|
972
|
-
|
|
977
|
+
textBlockWidth: true
|
|
973
978
|
})));
|
|
974
979
|
} finally {
|
|
975
980
|
_effect.f();
|
|
@@ -981,4 +986,4 @@ export {
|
|
|
981
986
|
ChannelContainer,
|
|
982
987
|
ChannelContainer_default
|
|
983
988
|
};
|
|
984
|
-
//# sourceMappingURL=chunk-
|
|
989
|
+
//# sourceMappingURL=chunk-F36NHPJG.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/components/ChannelContainer.tsx", "../../../src/components/Call/Call.tsx", "../../../src/components/Media/AudioStream.tsx", "../../../src/components/Media/VideoObject.tsx", "../../../src/components/Participant/Participant.tsx", "../../../src/components/ResponsiveGrid/ResponsiveContainer.tsx", "../../../src/components/ResponsiveGrid/ResponsiveGrid.tsx", "../../../src/components/ResponsiveGrid/ResponsiveGridItem.tsx", "../../../src/components/Participant/ParticipantGrid.tsx", "../../../src/components/Call/Toolbar.tsx"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Atom } from '@effect-atom/atom-react';\nimport React, { type ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { useCapabilities, useCapability } from '@dxos/app-framework/react';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { Obj } from '@dxos/echo';\nimport { log } from '@dxos/log';\nimport { useClient } from '@dxos/react-client';\nimport { getSpace } from '@dxos/react-client/echo';\nimport { useIdentity } from '@dxos/react-client/halo';\nimport { ElevationProvider, Input, useTranslation } from '@dxos/react-ui';\nimport { ControlGroup, ControlGroupButton, ControlItemInput } from '@dxos/react-ui-form';\nimport { MenuProvider, ToolbarMenu, createMenuAction, createMenuItemGroup, useMenuActions } from '@dxos/react-ui-menu';\nimport { useSoundEffect } from '@dxos/react-ui-sfx';\nimport { StackItem } from '@dxos/react-ui-stack';\n\nimport { ThreadCapabilities } from '../capabilities';\nimport { meta } from '../meta';\nimport { type Channel } from '../types';\n\nimport { Call } from './Call';\nimport ChatContainer from './ChatContainer';\n\n// TODO(burdon): Create Radix style layout.\n\nexport type ChannelContainerProps = {\n channel?: Channel.Channel;\n roomId?: string;\n role?: string;\n fullscreen?: boolean;\n};\n\n/**\n * Renders a call when active, otherwise renders the channel chat.\n */\nexport const ChannelContainer = ({ channel, roomId: _roomId, role, fullscreen }: ChannelContainerProps) => {\n const space = getSpace(channel);\n const callManager = useCapability(ThreadCapabilities.CallManager);\n const attendableId = channel ? Obj.getDXN(channel).toString() : undefined;\n const roomId = _roomId ?? attendableId ?? failUndefined();\n const identity = useIdentity();\n const isNamed = !!identity?.profile?.displayName;\n const joinSound = useSoundEffect('JoinCall');\n const leaveSound = useSoundEffect('LeaveCall');\n\n const extensions = useCapabilities(ThreadCapabilities.CallExtension);\n useEffect(() => {\n const ctx = new Context();\n callManager.left.on(ctx, (roomId) => {\n extensions.forEach((extension) => {\n void extension.onLeave?.(roomId);\n });\n });\n\n callManager.callStateUpdated.on(ctx, (state) => {\n extensions.forEach((extension) => {\n void extension.onCallStateUpdated?.(state);\n });\n });\n\n callManager.mediaStateUpdated.on(ctx, (state) => {\n extensions.forEach((extension) => {\n void extension.onMediaStateUpdated?.(state);\n });\n });\n\n return () => {\n void ctx.dispose();\n };\n }, [callManager, extensions]);\n\n /**\n * Join the call.\n */\n // TODO(wittjosiah): Show preview before joining?\n const handleJoin = useCallback(async () => {\n if (!roomId || !channel) {\n return;\n }\n\n if (callManager.joined) {\n await callManager.leave();\n }\n\n try {\n void joinSound.play();\n callManager.setRoomId(roomId);\n await callManager.join();\n await Promise.all(extensions.map((extension) => extension.onJoin?.({ channel, roomId })));\n } catch (err) {\n // TODO(burdon): Error sound.\n log.catch(err);\n }\n }, [extensions, channel, roomId]);\n\n /**\n * Leave the call.\n */\n const handleLeave = useCallback(async () => {\n try {\n void leaveSound.play();\n } catch (err) {\n // TODO(burdon): Error sound.\n log.catch(err);\n } finally {\n void callManager.turnAudioOff();\n void callManager.turnVideoOff();\n void callManager.turnScreenshareOff();\n void callManager.leave();\n }\n }, [extensions, roomId]);\n\n const isJoined = callManager.joined && callManager.roomId === roomId;\n\n return (\n <StackItem.Content classNames={isJoined && 'bs-full'} toolbar={!isJoined}>\n {isJoined && !isNamed && <DisplayNameMissing />}\n {isJoined && isNamed && (\n <Call.Root>\n <Call.Grid fullscreen={fullscreen} />\n <Call.Toolbar channel={channel} onLeave={handleLeave} />\n </Call.Root>\n )}\n {!isJoined && channel && channel.defaultThread.target && space && (\n <>\n <ChannelToolbar attendableId={attendableId} role={role} onJoinCall={handleJoin} />\n <ChatContainer space={space} thread={channel.defaultThread.target} classNames='container-max-width' />\n </>\n )}\n </StackItem.Content>\n );\n};\n\nexport default ChannelContainer;\n\nconst DisplayNameMissing = () => {\n const { t } = useTranslation(meta.id);\n const client = useClient();\n const [displayName, setDisplayName] = useState('');\n const handleChange = useCallback((event: ChangeEvent<HTMLInputElement>) => setDisplayName(event.target.value), []);\n const handleSave = useCallback(() => client.halo.updateProfile({ displayName }), [client, displayName]);\n\n return (\n <ControlGroup classNames='p-4 place-content-center'>\n <ControlItemInput title={t('display name label')} description={t('display name description')}>\n <Input.TextInput\n value={displayName}\n onChange={handleChange}\n placeholder={t('display name input placeholder')}\n classNames='md:min-is-64'\n />\n </ControlItemInput>\n <ControlGroupButton disabled={!displayName} onClick={handleSave}>\n {t('set display name label')}\n </ControlGroupButton>\n </ControlGroup>\n );\n};\n\nconst useChannelToolbarActions = (onJoinCall?: () => void) => {\n const creator = useMemo(\n () =>\n Atom.make(() => {\n return {\n nodes: [\n createMenuItemGroup('root', {\n label: ['channel toolbar title', { ns: meta.id }],\n }),\n createMenuAction('video-call', () => onJoinCall?.(), {\n label: ['start video call label', { ns: meta.id }],\n icon: 'ph--video-camera--regular',\n type: 'video-call',\n }),\n ],\n edges: [{ source: 'root', target: 'video-call' }],\n };\n }),\n [],\n );\n\n return useMenuActions(creator);\n};\n\ntype ChannelToolbarProps = {\n attendableId?: string;\n role?: string;\n onJoinCall?: () => void;\n};\n\nconst ChannelToolbar = ({ attendableId, role, onJoinCall }: ChannelToolbarProps) => {\n const menuProps = useChannelToolbarActions(onJoinCall);\n\n return (\n <ElevationProvider elevation={role === 'section' ? 'positioned' : 'base'}>\n <MenuProvider {...menuProps} attendableId={attendableId}>\n <ToolbarMenu textBlockWidth />\n </MenuProvider>\n </ElevationProvider>\n );\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { type FC, type PropsWithChildren } from 'react';\n\nimport { useCapability } from '@dxos/app-framework/react';\nimport { type ThemedClassName } from '@dxos/react-ui';\n\nimport { ThreadCapabilities } from '../../capabilities';\nimport { useDebugMode } from '../../hooks';\nimport { AudioStream } from '../Media';\nimport { ParticipantGrid } from '../Participant';\n\nimport { Toolbar, type ToolbarProps } from './Toolbar';\n\n//\n// Root\n//\n\ntype CallRootProps = PropsWithChildren<ThemedClassName>;\n\nconst CallRoot: FC<CallRootProps> = ({ children }) => {\n return <div className='relative flex flex-col grow overflow-hidden'>{children}</div>;\n};\n\nCallRoot.displayName = 'CallRoot';\n\n//\n// Audio\n//\n\ntype CallAudioProps = {};\n\nconst CallAudio: FC<CallAudioProps> = () => {\n const call = useCapability(ThreadCapabilities.CallManager);\n\n return <AudioStream tracks={call.audioTracksToPlay} />;\n};\n\nCallAudio.displayName = 'CallAudio';\n\n//\n// Room\n//\n\ntype CallGridProps = {\n fullscreen?: boolean;\n};\n\nconst CallGrid: FC<CallGridProps> = ({ fullscreen }) => {\n const debug = useDebugMode();\n const call = useCapability(ThreadCapabilities.CallManager);\n\n return (\n <div className='grid grow p-4 dark:bg-neutral-900'>\n <ParticipantGrid self={call.self} users={call.users} debug={debug} fullscreen={fullscreen} />\n </div>\n );\n};\n\nCallGrid.displayName = 'CallGrid';\n\n//\n// Toolbar\n//\n\ntype CallToolbarProps = Pick<ToolbarProps, 'channel' | 'onLeave'>;\n\nconst CallToolbar: FC<CallToolbarProps> = (props) => {\n return (\n <div className='absolute bottom-0 left-0 right-0 flex justify-center'>\n <Toolbar isInRoom {...props} />\n </div>\n );\n};\n\nCallToolbar.displayName = 'CallToolbar';\n\n//\n// Export\n//\n\nexport const Call = {\n Root: CallRoot,\n Grid: CallGrid,\n Audio: CallAudio,\n Toolbar: CallToolbar,\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport React, { type FC, useEffect, useRef } from 'react';\n\nexport type AudioStreamProps = {\n tracks: MediaStreamTrack[];\n};\n\nexport const AudioStream: FC<AudioStreamProps> = ({ tracks }) => {\n const mediaStreamRef = useRef(new MediaStream());\n const ref = useRef<HTMLAudioElement>(null);\n\n useEffect(() => {\n const audio = ref.current;\n if (!audio) {\n return;\n }\n\n const mediaStream = mediaStreamRef.current;\n audio.srcObject = mediaStream;\n }, []);\n\n const resetSrcObject = () => {\n const audio = ref.current;\n const mediaStream = mediaStreamRef.current;\n if (!audio || !mediaStream) {\n return;\n }\n\n // Need to set srcObject again in Chrome and call play() again for Safari\n // https://www.youtube.com/live/Tkx3OGrwVk8?si=K--P_AzNnAGrjraV&t=2533\n // Calling play() this way to make Chrome happy otherwise it throws an error.\n audio.addEventListener('canplay', () => audio.play(), { once: true });\n audio.srcObject = mediaStream;\n };\n\n return (\n <>\n <audio ref={ref} autoPlay />\n {tracks.map((track) => (\n <AudioTrack key={track.id} track={track} mediaStream={mediaStreamRef.current} resetSrcObject={resetSrcObject} />\n ))}\n </>\n );\n};\n\ntype AudioTrackProps = {\n track: MediaStreamTrack;\n mediaStream: MediaStream;\n resetSrcObject: () => void;\n};\n\nconst AudioTrack = ({ track, mediaStream, resetSrcObject }: AudioTrackProps) => {\n useEffect(() => {\n const currentTrack = track;\n mediaStream.addTrack(currentTrack);\n resetSrcObject();\n return () => {\n mediaStream.removeTrack(currentTrack);\n resetSrcObject();\n };\n }, [track, mediaStream]);\n\n return null;\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport React, { type JSX, forwardRef, memo, useEffect, useRef } from 'react';\n\nimport { type ThemedClassName } from '@dxos/react-ui';\nimport { mx } from '@dxos/react-ui-theme';\n\nexport type VideoObjectProps = Omit<JSX.IntrinsicElements['video'], 'className' | 'ref'> &\n ThemedClassName<{\n videoStream?: MediaStream;\n flip?: boolean;\n // TODO(burdon): If screenshare then contain.\n contain?: boolean;\n }>;\n\nexport const VideoObject = memo(\n forwardRef<HTMLVideoElement, VideoObjectProps>(({ videoStream, classNames, flip, contain, ...rest }, ref) => {\n const internalRef = useRef<HTMLVideoElement | null>(null);\n\n useEffect(() => {\n const video = internalRef.current;\n if (video && videoStream) {\n video.srcObject = videoStream;\n video.setAttribute('autoplay', 'true');\n video.setAttribute('playsinline', 'true');\n }\n }, [videoStream, internalRef.current]);\n\n // NOTE: The video element typically has a max size of 1280x720.\n return (\n <video\n className={mx(\n 'is-full aspect-video',\n flip && 'scale-x-[-1]',\n contain ? 'object-contain' : 'object-cover',\n classNames,\n )}\n ref={(v) => {\n internalRef.current = v;\n if (ref === null) {\n return;\n }\n\n if (typeof ref === 'function') {\n ref(v);\n } else {\n ref.current = v;\n }\n }}\n {...rest}\n />\n );\n }),\n);\n\nVideoObject.displayName = 'VideoObject';\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport React, { memo, useMemo } from 'react';\n\nimport { useCapability } from '@dxos/app-framework/react';\n\nimport { type EncodedTrackName, type UserState } from '../../calls';\nimport { ThreadCapabilities } from '../../capabilities';\nimport { VideoObject } from '../Media';\nimport { ResponsiveGridItem, type ResponsiveGridItemProps } from '../ResponsiveGrid';\n\nexport const SCREENSHARE_SUFFIX = '_screenshare';\n\nexport const Participant = memo(({ item: user, debug, ...props }: ResponsiveGridItemProps<UserState>) => {\n const call = useCapability(ThreadCapabilities.CallManager);\n const isSelf: boolean = call.self.id !== undefined && user.id !== undefined && user.id.startsWith(call.self.id);\n const isScreenshare = user.id?.endsWith(SCREENSHARE_SUFFIX);\n\n const pulledVideoStream =\n !isSelf && isScreenshare && user.tracks?.screenshareEnabled\n ? call.getVideoStream(user.tracks?.screenshare as EncodedTrackName)\n : !isSelf && !isScreenshare && user.tracks?.videoEnabled\n ? call.getVideoStream(user.tracks?.video as EncodedTrackName)\n : undefined;\n\n const videoStream = useMemo<MediaStream | undefined>(() => {\n if (isSelf) {\n if (isScreenshare) {\n return call.media.screenshareVideoStream;\n } else if (!isScreenshare) {\n return call.media.videoStream;\n }\n } else if (!isSelf) {\n return pulledVideoStream;\n }\n }, [isSelf, isScreenshare, call.media.videoStream, call.media.screenshareVideoStream, pulledVideoStream]);\n\n return (\n <ResponsiveGridItem\n {...props}\n item={user}\n name={user.name}\n self={isSelf}\n screenshare={!!call.media.screenshareVideoStream}\n video={call.media.videoEnabled}\n mute={user ? !user.tracks?.audioEnabled : false}\n wave={user.raisedHand}\n speaking={user.speaking}\n debug={debug}\n >\n <VideoObject\n videoStream={videoStream}\n flip={isSelf && !isScreenshare}\n contain={!!isScreenshare}\n classNames='rounded-md'\n />\n </ResponsiveGridItem>\n );\n});\n\nParticipant.displayName = 'Participant';\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { type PropsWithChildren } from 'react';\n\nimport { mx } from '@dxos/react-ui-theme';\n\n/**\n * A container component that maintains the child's aspect ratio while centering its content.\n * The container will scale to fit within its parent's bounds while preserving the aspect ratio.\n *\n * @example\n * <ResponsiveContainer>\n * <VideoObject />\n * </ResponsiveContainer>\n */\nexport const ResponsiveContainer = ({ children }: PropsWithChildren) => {\n return (\n // Outer container that takes full size of parent.\n <div role='none' className='relative flex is-full bs-full'>\n {/* Absolute positioning layer for centering content. */}\n <div role='none' className='absolute inset-0 flex justify-center items-center'>\n {/* Content container that maintains given aspect ratio and proper scaling. */}\n <div role='none' className={mx('max-bs-full max-is-full is-auto bs-auto aspect-video')}>\n {children}\n </div>\n </div>\n </div>\n );\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { type ComponentType, type FC, useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';\nimport { useResizeDetector } from 'react-resize-detector';\n\nimport { invariant } from '@dxos/invariant';\nimport { type ThemedClassName } from '@dxos/react-ui';\nimport { type Size } from '@dxos/react-ui-dnd';\nimport { mx } from '@dxos/react-ui-theme';\n\nimport { ResponsiveContainer } from './ResponsiveContainer';\nimport { type ResponsiveGridItemProps } from './ResponsiveGridItem';\n\nconst ASPECT_RATIO = 16 / 9;\nconst MIN_GALLERY_HEIGHT = 250;\n\nconst DEFAULT_GAP = 8;\n\nconst maxImageSize = 'is-[2560px] bs-[1440px]';\n\n/**\n * Props for the ResponsiveGrid component.\n */\nexport type ResponsiveGridProps<T extends object = any> = ThemedClassName<{\n /** Cell component. */\n Cell: ComponentType<ResponsiveGridItemProps<T>>;\n\n /** Space between grid items in pixels. */\n gap?: number;\n\n /** Function to get the ID of an item. */\n getId?: (item: T) => string;\n\n /** Array of items to display in the grid. */\n items: T[];\n\n /** ID of the pinned item. */\n pinned?: string;\n\n /** Whether to hide the gallery (unpinned items) when an item is pinned. */\n autoHideGallery?: boolean;\n\n /** Whether the divider is resizable. */\n resizable?: boolean;\n\n /** Debug mode. */\n debug?: boolean;\n\n /** Callback when the pinned item changes. */\n onPinnedChange?: (pinned: string | undefined) => void;\n}>;\n\nconst defaultGetId: ResponsiveGridProps<any>['getId'] = (item: any) => item.id;\n\n/**\n * A responsive grid component that automatically adjusts its layout to optimize space usage.\n * Maintains aspect ratio of items while ensuring uniform gaps between them.\n */\nexport const ResponsiveGrid = <T extends object = any>({\n classNames,\n Cell,\n gap = DEFAULT_GAP,\n getId = defaultGetId,\n items,\n pinned,\n autoHideGallery = false,\n debug,\n onPinnedChange,\n}: ResponsiveGridProps<T>) => {\n const {\n width: containerWidth = 0,\n height: containerHeight = 0,\n ref: containerRef,\n } = useResizeDetector<HTMLDivElement>({ refreshRate: 100 });\n const [dividerHeight, setDividerHeight] = useState<Size>(0);\n useEffect(() => {\n if (containerWidth && containerHeight) {\n const { height } = fitAspectRatio(containerWidth, containerHeight, ASPECT_RATIO);\n setDividerHeight(Math.min(height, containerHeight - MIN_GALLERY_HEIGHT));\n }\n }, [containerWidth, containerHeight]);\n\n const pinnedItem = useMemo(() => items.find((item) => getId(item) === pinned), [items, pinned]);\n const mainItems = useMemo(() => items.filter((item) => getId(item) !== pinned), [items, pinned]);\n const hideGallery = autoHideGallery && pinnedItem !== undefined;\n\n //\n // Recalculate optimal layout when container size or items change.\n //\n const [{ time, columns, cellWidth }, setLayout] = useState<Layout>({ time: 0, columns: 0, cellWidth: 0 });\n const { width = 0, height = 0, ref: gridContainerRef } = useResizeDetector<HTMLDivElement>({ refreshRate: 200 });\n useEffect(() => {\n if (containerHeight && width && height) {\n const layout = calculateLayout(width, height, mainItems.length, gap);\n setLayout({ time: Date.now(), ...layout });\n }\n }, [containerHeight, width, height, mainItems.length, gap, pinned]);\n\n //\n // We use the browser to layout invisible divs and then calculate the absolute position of these items,\n // which are animated into position.\n //\n const [bounds, setBounds] = useState<[T, DOMRectBounds][]>([]);\n useLayoutEffect(() => {\n if ((!hideGallery && !gridContainerRef.current) || !containerHeight) {\n return;\n }\n\n // TODO(burdon): Consider directly setting bounds on DOM elementsinstead of state update?\n const t = setTimeout(() => {\n setBounds(\n items\n .filter((item) => !hideGallery || item === pinnedItem)\n .map((item) => {\n invariant(containerRef.current);\n const el = containerRef.current.querySelector(`[data-grid-item=\"${getId(item)}\"]`);\n if (!el) {\n return null;\n }\n\n const bounds = getRelativeBounds(containerRef.current, el as HTMLElement);\n return [item, bounds];\n })\n .filter((item): item is [T, DOMRectBounds] => item !== null),\n );\n });\n\n return () => clearTimeout(t);\n }, [containerHeight, items, pinnedItem, hideGallery, time]);\n\n const handleClick = useCallback(\n (item: T) => onPinnedChange?.(getId(item) === pinned ? undefined : getId(item)),\n [pinned, onPinnedChange],\n );\n\n return (\n <div ref={containerRef} className={mx('relative is-full bs-full', classNames)}>\n {/* Placeholder elements to calculate layout. */}\n <div className='absolute inset-0 flex flex-col grow gap-2'>\n {/* Pinned item. */}\n {pinnedItem && (\n <div\n className={mx('flex grow-[2] shrink overflow-hidden justify-center items-center', hideGallery && 'bs-full')}\n style={hideGallery ? {} : { height: dividerHeight }}\n >\n <SoloItem id={getId(pinnedItem)} debug={debug} />\n </div>\n )}\n\n {/* Gallery. */}\n {!hideGallery && (\n <div\n ref={gridContainerRef}\n className='flex grow-[1] overflow-hidden justify-center items-center'\n style={hideGallery ? {} : { minHeight: MIN_GALLERY_HEIGHT }}\n >\n {mainItems.length === 1 && (\n <div style={{ width: cellWidth }} className='flex bs-full'>\n <SoloItem id={getId(mainItems[0])} debug={debug} />\n </div>\n )}\n\n {mainItems.length > 1 && columns > 0 && (\n <div\n role='grid'\n style={{\n display: 'grid',\n gridTemplateColumns: `repeat(${columns}, ${cellWidth}px)`,\n gap: `${gap}px`,\n }}\n >\n {mainItems.map((item) => (\n <div\n key={getId(item)}\n {...{ 'data-grid-item': getId(item) }}\n className={mx(\n 'aspect-video max-bs-full max-is-full is-auto bs-auto',\n debug && 'border border-primary-500',\n )}\n />\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Absolutely positioned items. */}\n <div className={mx(debug && 'opacity-10')}>\n {bounds.map(([item, bounds]) => (\n <Cell\n key={getId(item)}\n classNames='absolute transition-all duration-500'\n item={item}\n style={bounds}\n pinned={getId(item) === pinned}\n onClick={items.length > 1 ? handleClick : undefined}\n />\n ))}\n </div>\n </div>\n );\n};\n\nconst SoloItem: FC<Pick<ResponsiveGridProps, 'debug'> & { id: string }> = ({ debug, id }) => {\n return (\n <ResponsiveContainer>\n <div\n {...{ 'data-grid-item': id }}\n className={mx('aspect-video overflow-hidden', debug && 'z-20 border-2 border-primary-500')}\n >\n {/* Maximum size placeholder image forces aspect ratio. */}\n <img alt='placeholder video' className={mx('opacity-0', maxImageSize)} />\n </div>\n </ResponsiveContainer>\n );\n};\n\ntype DOMRectBounds = Pick<DOMRect, 'top' | 'left' | 'width' | 'height'>;\n\n// TODO(burdon): Reconcile with react-ui-gameboard.\nconst getRelativeBounds = (container: HTMLElement, el: HTMLElement): DOMRectBounds => {\n const containerRect = container.getBoundingClientRect();\n const elementRect = el.getBoundingClientRect();\n return {\n top: elementRect.top - containerRect.top,\n left: elementRect.left - containerRect.left,\n width: elementRect.width,\n height: elementRect.height,\n };\n};\n\ntype Layout = {\n time?: number;\n columns: number;\n cellWidth: number;\n};\n\n/**\n * Calculates the optimal number of columns for a grid layout that minimizes wasted space.\n * @param containerWidth - Width of the container in pixels.\n * @param containerHeight - Height of the container in pixels.\n * @param count - Total number of items to display.\n * @param gap - Space between items in pixels.\n * @param aspectRatio - Desired aspect ratio of items (width/height).\n * @returns The optimal number of columns.\n */\nconst calculateLayout = (\n containerWidth: number,\n containerHeight: number,\n count: number,\n gap: number,\n aspectRatio = ASPECT_RATIO,\n): Layout => {\n if (count === 0) {\n return { columns: 1, cellWidth: 1 };\n }\n\n let minWastedSpace = Infinity;\n let bestColumns = 1;\n let cellWidth = 0;\n\n // Try different rows counts to find the optimal layout that minimizes wasted space.\n for (let rows = 1; rows <= count; rows++) {\n const cols = Math.ceil(count / rows);\n\n // Calculate available space accounting for gaps.\n const { width: itemWidth, height: itemHeight } = fitItemsToGrid(\n containerWidth,\n containerHeight,\n cols,\n rows,\n aspectRatio,\n gap,\n );\n\n // Calculate total wasted space for this configuration.\n const usedWidth = itemWidth * cols + gap * cols - 1;\n const usedHeight = itemHeight * rows + gap * rows - 1;\n\n // Determine if optimal.\n const wastedSpace = containerWidth * containerHeight - usedWidth * usedHeight;\n if (wastedSpace < minWastedSpace) {\n minWastedSpace = wastedSpace;\n bestColumns = cols;\n cellWidth = itemWidth;\n }\n }\n\n return { columns: bestColumns, cellWidth };\n};\n\n/**\n * Returns the size of the largest rectangle with the given aspect ration that fits within the grid.\n */\nconst fitItemsToGrid = (\n outerWidth: number,\n outerHeight: number,\n numCols: number,\n numRows: number,\n aspectRatio: number,\n gap: number,\n): { width: number; height: number } => {\n // Calculate available space accounting for gaps.\n const availableWidth = outerWidth - gap * (numCols - 1);\n const availableHeight = outerHeight - gap * (numRows - 1);\n\n // Calculate max dimensions.\n const maxCellWidth = availableWidth / numCols;\n const maxCellHeight = availableHeight / numRows;\n\n // Use fitAspectRatio to get dimensions that fit within max cell size while maintaining the desired aspect ratio\n return fitAspectRatio(maxCellWidth, maxCellHeight, aspectRatio);\n};\n\n/**\n * Returns the size of the largest rectangle the given aspect ratio that fits within the outer rectangle.\n */\nconst fitAspectRatio = (\n outerWidth: number,\n outerHeight: number,\n aspectRatio: number,\n): { width: number; height: number } => {\n if (outerWidth <= 0 || outerHeight <= 0 || aspectRatio <= 0) {\n return { width: 0, height: 0 };\n }\n\n // First try fitting to width.\n let width = outerWidth;\n let height = width / aspectRatio;\n\n // If too tall, fit to height instead.\n if (height > outerHeight) {\n height = outerHeight;\n width = height * aspectRatio;\n }\n\n return { width, height };\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { type CSSProperties, type PropsWithChildren, useEffect, useState } from 'react';\n\nimport { Icon, IconButton, type ThemedClassName, useTranslation } from '@dxos/react-ui';\nimport { Waveform } from '@dxos/react-ui-sfx';\nimport { groupHoverControlItemWithTransition, mx } from '@dxos/react-ui-theme';\n\nimport { meta } from '../../meta';\n\nexport type ResponsiveGridItemProps<T extends object = any> = PropsWithChildren<\n ThemedClassName<{\n item: T;\n style?: CSSProperties;\n pinned?: boolean;\n name?: string;\n self?: boolean;\n screenshare?: boolean;\n video?: boolean;\n mute?: boolean;\n wave?: boolean;\n speaking?: boolean;\n debug?: boolean;\n onClick?: (item: T) => void;\n }>\n>;\n\n/**\n * Cell container.\n */\nexport const ResponsiveGridItem = <T extends object = any>({\n children,\n classNames,\n item,\n style,\n name,\n self,\n pinned,\n screenshare,\n video,\n mute,\n wave,\n speaking,\n onClick,\n}: ResponsiveGridItemProps<T>) => {\n const { t } = useTranslation(meta.id);\n const iconProps: Record<string, { icon: string; label: string; classNames?: string }> = {\n wave: {\n icon: 'ph--hand-waving--duotone',\n label: t('icon wave'),\n classNames: 'animate-pulse bg-orange-500',\n },\n mute: {\n icon: 'ph--microphone-slash--regular',\n label: t('icon muted'),\n },\n };\n\n const props = wave && !pinned ? iconProps.wave : mute ? iconProps.mute : speaking ? iconProps.speaking : undefined;\n\n // Debounce speaking indicator.\n const [speakingIndicator, setSpeakingIndicator] = useState(speaking);\n useEffect(() => {\n if (speaking) {\n setSpeakingIndicator(true);\n } else {\n const timeout = setTimeout(() => {\n setSpeakingIndicator(false);\n }, 1_000);\n return () => clearTimeout(timeout);\n }\n }, [speaking]);\n\n return (\n <div\n className={mx(\n 'relative is-full bs-full group',\n 'rounded-md outline outline-2 outline-neutral-900 transition-[outline-color] duration-500',\n speakingIndicator ? 'outline-green-500' : !video && 'outline-separator',\n classNames,\n )}\n style={style}\n >\n {children}\n\n {/* Action. */}\n {onClick && (\n <div className='z-10 absolute top-1 right-1 flex'>\n <IconButton\n classNames={mx('p-1 min-bs-1 rounded', groupHoverControlItemWithTransition)}\n iconOnly\n icon={pinned ? 'ph--x--regular' : 'ph--arrows-out--regular'}\n size={pinned ? 5 : 4}\n label={pinned ? t('icon unpin') : t('icon pin')}\n onClick={() => onClick?.(item)}\n />\n </div>\n )}\n\n {/* Name. */}\n {name && (\n <div className='z-10 absolute bottom-1 left-8 right-1 flex justify-end gap-1 items-center'>\n {/* TODO(burdon): Replace with avatar for everyone. */}\n {/* {self && <Icon icon='ph--asterisk--regular' size={pinned ? 5 : 4} />} */}\n {screenshare && <Icon icon='ph--broadcast--regular' size={pinned ? 5 : 4} />}\n <div\n className={mx(\n 'bg-neutral-800 text-neutral-100 plb-0.5 truncate rounded',\n pinned ? 'pli-2' : 'pli-1 text-xs',\n )}\n >\n {name}\n </div>\n </div>\n )}\n\n {/* Activity. */}\n <div className='z-10 absolute bottom-1 left-1 flex'>\n {(speaking && <Waveform active size={pinned ? 5 : 4} />) ||\n (props && (\n <IconButton\n classNames={mx('p-1 min-bs-1 rounded', props?.classNames)}\n icon={props?.icon}\n label={props?.label}\n size={pinned ? 5 : 4}\n iconOnly\n />\n ))}\n </div>\n </div>\n );\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { useEffect, useMemo, useState } from 'react';\n\nimport { type ThemedClassName } from '@dxos/react-ui';\n\nimport { type UserState } from '../../calls';\nimport { ResponsiveGrid } from '../ResponsiveGrid';\n\nimport { Participant, SCREENSHARE_SUFFIX } from './Participant';\n\nconst getId = (user: UserState): string => user.id!;\n\nexport type ParticipantGridProps = ThemedClassName<{\n self: UserState;\n users: UserState[];\n fullscreen?: boolean;\n debug?: boolean;\n}>;\n\nexport const ParticipantGrid = ({ classNames, self, users, fullscreen, debug }: ParticipantGridProps) => {\n const [pinned, setPinned] = useState<string | undefined>();\n\n const allUsers = useMemo(() => {\n const allUsers: (UserState & { isSelf?: boolean })[] = [];\n users.forEach((user) => {\n if (!user.joined) {\n return;\n }\n\n allUsers.push({ ...user, isSelf: user.id === self.id });\n if (user.tracks?.screenshareEnabled) {\n const screenshare: UserState = {\n ...user,\n id: user.id + SCREENSHARE_SUFFIX,\n tracks: {\n ...user.tracks,\n video: user.tracks.screenshare,\n videoEnabled: user.tracks.screenshareEnabled,\n } as any, // TODO(burdon): Remove cast.\n };\n\n allUsers.push(screenshare);\n }\n });\n\n return allUsers;\n }, [self, users]);\n\n useEffect(() => {\n if (pinned) {\n // Check expanded user is still in call.\n if (!allUsers.find((user) => user.id === pinned)) {\n setPinned(undefined);\n }\n }\n }, [pinned, allUsers]);\n\n // TODO(burdon): Put self last.\n const sortedUsers: UserState[] = allUsers.sort((a, b) => {\n if (a.isSelf) {\n return 1;\n } else if (b.isSelf) {\n return -1;\n } else if (a.tracks?.screenshareEnabled) {\n return -1;\n } else if (b.tracks?.screenshareEnabled) {\n return 1;\n } else {\n return 0;\n }\n });\n\n // TODO(burdon): Show ghost view of user for a second before leaving.\n return (\n <ResponsiveGrid<UserState>\n classNames={classNames}\n Cell={Participant}\n debug={debug}\n getId={getId}\n items={sortedUsers}\n pinned={pinned}\n autoHideGallery={fullscreen}\n onPinnedChange={setPinned}\n />\n );\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport React from 'react';\n\nimport { useAppGraph, useCapability } from '@dxos/app-framework/react';\nimport { Obj } from '@dxos/echo';\nimport { useActions, useNode } from '@dxos/plugin-graph';\nimport {\n Icon,\n IconButton,\n type IconButtonProps,\n Toolbar as NaturalToolbar,\n type ThemedClassName,\n toLocalizedString,\n useTranslation,\n} from '@dxos/react-ui';\nimport { groupHoverControlItemWithTransition, mx } from '@dxos/react-ui-theme';\n\nimport { ThreadCapabilities } from '../../capabilities';\nimport { meta } from '../../meta';\nimport { type Channel } from '../../types';\n\nexport type ToolbarProps = ThemedClassName<{\n channel?: Channel.Channel;\n participants?: number;\n autoHideControls?: boolean;\n isInRoom?: boolean;\n onJoin?: () => void;\n onLeave?: () => void;\n}>;\n\n// TODO(wittjosiah): Use ToolbarMenu.\nexport const Toolbar = ({\n classNames,\n channel,\n participants,\n autoHideControls = true,\n onJoin,\n onLeave,\n}: ToolbarProps) => {\n const { t } = useTranslation(meta.id);\n const { graph } = useAppGraph();\n const call = useCapability(ThreadCapabilities.CallManager);\n\n // Channel app graph node.\n const node = useNode(graph, channel && Obj.getDXN(channel).toString());\n const actions = useActions(graph, node?.id).filter((action) => action.properties.disposition === 'toolbar');\n\n // Screen sharing.\n const isScreensharing = call.media.screenshareTrack !== undefined;\n const canSharescreen =\n typeof navigator.mediaDevices !== 'undefined' && navigator.mediaDevices.getDisplayMedia !== undefined;\n\n // TODO(wittjosiah): In order to use toolbar, need to update to actually use the graph action callbacks directly.\n return (\n <div className={mx('z-20 flex justify-center m-8', autoHideControls && groupHoverControlItemWithTransition)}>\n <NaturalToolbar.Root classNames={['p-2 bg-modalSurface rounded-md shadow-md', classNames]}>\n <ToggleButton\n active={call.media.audioEnabled}\n state={{\n on: {\n icon: 'ph--microphone--regular',\n label: t('mic off'),\n onClick: () => call.turnAudioOff(),\n classNames: 'bg-callActive',\n },\n off: {\n icon: 'ph--microphone-slash--duotone',\n label: t('mic on'),\n onClick: () => call.turnAudioOn(),\n classNames: [call.joined && 'bg-callAlert'],\n },\n }}\n />\n <ToggleButton\n active={call.media.videoEnabled}\n state={{\n on: {\n icon: 'ph--video-camera--regular',\n label: t('camera off'),\n onClick: () => call.turnVideoOff(),\n },\n off: {\n icon: 'ph--video-camera-slash--duotone',\n label: t('camera on'),\n onClick: () => call.turnVideoOn(),\n },\n }}\n />\n\n {(participants !== undefined && (\n <div className='flex justify-center items-center gap-2 is-[5rem] text-xs text-subdued'>\n <Icon icon='ph--users--regular' size={4} />\n <div>{participants}</div>\n </div>\n )) || <NaturalToolbar.Separator variant='gap' />}\n\n {call.joined && (\n <>\n <ToggleButton\n disabled={!canSharescreen}\n active={isScreensharing}\n state={{\n on: {\n icon: 'ph--monitor--regular',\n label: t('screenshare off'),\n onClick: () => call.turnScreenshareOff(),\n },\n off: {\n icon: 'ph--monitor-arrow-up--duotone',\n label: t('screenshare on'),\n onClick: () => call.turnScreenshareOn(),\n },\n }}\n />\n\n {/* Companion actions. */}\n {actions.map((action) => (\n <IconButton\n key={action.id}\n {...defaultButtonProps}\n icon={action.properties.icon}\n label={toLocalizedString(action.properties.label, t)}\n classNames={action.properties.classNames}\n onClick={() => action.data({ node })}\n />\n ))}\n\n <ToggleButton\n active={call.raisedHand}\n state={{\n on: {\n icon: 'ph--hand-waving--regular',\n label: t('lower hand'),\n onClick: () => call.setRaisedHand(false),\n classNames: [call.joined && 'bg-callAlert'],\n },\n off: {\n icon: 'ph--hand-palm--duotone',\n label: t('raise hand'),\n onClick: () => call.setRaisedHand(true),\n },\n }}\n />\n </>\n )}\n {call.joined ? (\n <IconButton variant='destructive' icon='ph--phone-x--regular' label={t('leave call')} onClick={onLeave} />\n ) : (\n <IconButton variant='primary' icon='ph--phone-incoming--regular' label={t('join call')} onClick={onJoin} />\n )}\n </NaturalToolbar.Root>\n </div>\n );\n};\n\nToolbar.displayName = 'MeetingToolbar';\n\ntype ToolbarButtonProps = Pick<IconButtonProps, 'disabled'> & {\n active?: boolean;\n state: {\n on: Pick<IconButtonProps, 'icon' | 'label' | 'onClick' | 'classNames'>;\n off: Pick<IconButtonProps, 'icon' | 'label' | 'onClick' | 'classNames'>;\n };\n};\n\nconst defaultButtonProps: Partial<IconButtonProps> = {\n size: 5,\n iconOnly: true,\n};\n\nconst ToggleButton = ({ active, state }: ToolbarButtonProps) => (\n <IconButton\n {...defaultButtonProps}\n classNames={[active ? (state.on.classNames ?? 'bg-callActive') : state.off.classNames]}\n icon={active ? state.on.icon : state.off.icon}\n label={active ? state.on.label : state.off.label}\n onClick={active ? state.on.onClick : state.off.onClick}\n />\n);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Atom", "React", "useCallback", "useEffect", "useMemo", "useState", "useCapabilities", "useCapability", "Context", "failUndefined", "Obj", "log", "useClient", "getSpace", "useIdentity", "ElevationProvider", "Input", "useTranslation", "ControlGroup", "ControlGroupButton", "ControlItemInput", "MenuProvider", "ToolbarMenu", "createMenuAction", "createMenuItemGroup", "useMenuActions", "useSoundEffect", "StackItem", "React", "useCapability", "React", "useEffect", "useRef", "AudioStream", "tracks", "mediaStreamRef", "useRef", "MediaStream", "ref", "useEffect", "audio", "current", "mediaStream", "srcObject", "resetSrcObject", "addEventListener", "play", "once", "autoPlay", "map", "track", "AudioTrack", "key", "id", "currentTrack", "addTrack", "removeTrack", "React", "forwardRef", "memo", "useEffect", "useRef", "mx", "VideoObject", "memo", "forwardRef", "videoStream", "classNames", "flip", "contain", "rest", "ref", "internalRef", "useRef", "useEffect", "video", "current", "srcObject", "setAttribute", "React", "className", "mx", "v", "displayName", "React", "memo", "useMemo", "useCapability", "React", "mx", "ResponsiveContainer", "children", "React", "div", "role", "className", "mx", "React", "useCallback", "useEffect", "useLayoutEffect", "useMemo", "useState", "useResizeDetector", "invariant", "mx", "ASPECT_RATIO", "MIN_GALLERY_HEIGHT", "DEFAULT_GAP", "maxImageSize", "defaultGetId", "item", "id", "ResponsiveGrid", "classNames", "Cell", "gap", "getId", "items", "pinned", "autoHideGallery", "debug", "onPinnedChange", "width", "containerWidth", "height", "containerHeight", "ref", "containerRef", "useResizeDetector", "refreshRate", "dividerHeight", "setDividerHeight", "useState", "useEffect", "fitAspectRatio", "Math", "min", "pinnedItem", "useMemo", "find", "mainItems", "filter", "hideGallery", "undefined", "time", "columns", "cellWidth", "setLayout", "gridContainerRef", "layout", "calculateLayout", "length", "Date", "now", "bounds", "setBounds", "useLayoutEffect", "current", "t", "setTimeout", "map", "invariant", "el", "querySelector", "getRelativeBounds", "clearTimeout", "handleClick", "useCallback", "React", "div", "className", "mx", "style", "SoloItem", "minHeight", "role", "display", "gridTemplateColumns", "key", "onClick", "ResponsiveContainer", "img", "alt", "container", "containerRect", "getBoundingClientRect", "elementRect", "top", "left", "count", "aspectRatio", "minWastedSpace", "Infinity", "bestColumns", "rows", "cols", "ceil", "itemWidth", "itemHeight", "fitItemsToGrid", "usedWidth", "usedHeight", "wastedSpace", "outerWidth", "outerHeight", "numCols", "numRows", "availableWidth", "availableHeight", "maxCellWidth", "maxCellHeight", "React", "useEffect", "useState", "Icon", "IconButton", "useTranslation", "Waveform", "groupHoverControlItemWithTransition", "mx", "ResponsiveGridItem", "children", "classNames", "item", "style", "name", "self", "pinned", "screenshare", "video", "mute", "wave", "speaking", "onClick", "t", "useTranslation", "meta", "id", "iconProps", "icon", "label", "props", "undefined", "speakingIndicator", "setSpeakingIndicator", "useState", "useEffect", "timeout", "setTimeout", "clearTimeout", "React", "div", "className", "mx", "IconButton", "groupHoverControlItemWithTransition", "iconOnly", "size", "Icon", "Waveform", "active", "SCREENSHARE_SUFFIX", "Participant", "memo", "item", "user", "debug", "props", "call", "useCapability", "ThreadCapabilities", "CallManager", "isSelf", "self", "id", "undefined", "startsWith", "isScreenshare", "endsWith", "pulledVideoStream", "tracks", "screenshareEnabled", "getVideoStream", "screenshare", "videoEnabled", "video", "videoStream", "useMemo", "media", "screenshareVideoStream", "React", "ResponsiveGridItem", "name", "mute", "audioEnabled", "wave", "raisedHand", "speaking", "VideoObject", "flip", "contain", "classNames", "displayName", "React", "useEffect", "useMemo", "useState", "getId", "user", "id", "ParticipantGrid", "classNames", "self", "users", "fullscreen", "debug", "pinned", "setPinned", "useState", "allUsers", "useMemo", "forEach", "joined", "push", "isSelf", "tracks", "screenshareEnabled", "screenshare", "SCREENSHARE_SUFFIX", "video", "videoEnabled", "useEffect", "find", "undefined", "sortedUsers", "sort", "a", "b", "React", "ResponsiveGrid", "Cell", "Participant", "items", "autoHideGallery", "onPinnedChange", "React", "useAppGraph", "useCapability", "Obj", "useActions", "useNode", "Icon", "IconButton", "Toolbar", "NaturalToolbar", "toLocalizedString", "useTranslation", "groupHoverControlItemWithTransition", "mx", "Toolbar", "classNames", "channel", "participants", "autoHideControls", "onJoin", "onLeave", "t", "useTranslation", "meta", "id", "graph", "useAppGraph", "call", "useCapability", "ThreadCapabilities", "CallManager", "node", "useNode", "Obj", "getDXN", "toString", "actions", "useActions", "filter", "action", "properties", "disposition", "isScreensharing", "media", "screenshareTrack", "undefined", "canSharescreen", "navigator", "mediaDevices", "getDisplayMedia", "React", "div", "className", "mx", "groupHoverControlItemWithTransition", "NaturalToolbar", "Root", "ToggleButton", "active", "audioEnabled", "state", "on", "icon", "label", "onClick", "turnAudioOff", "off", "turnAudioOn", "joined", "videoEnabled", "turnVideoOff", "turnVideoOn", "Icon", "size", "Separator", "variant", "disabled", "turnScreenshareOff", "turnScreenshareOn", "map", "IconButton", "key", "defaultButtonProps", "toLocalizedString", "data", "raisedHand", "setRaisedHand", "displayName", "iconOnly", "CallRoot", "children", "React", "div", "className", "displayName", "CallAudio", "call", "useCapability", "ThreadCapabilities", "CallManager", "AudioStream", "tracks", "audioTracksToPlay", "CallGrid", "fullscreen", "debug", "useDebugMode", "ParticipantGrid", "self", "users", "CallToolbar", "props", "Toolbar", "isInRoom", "Call", "Root", "Grid", "Audio", "ChannelContainer", "channel", "roomId", "_roomId", "role", "fullscreen", "space", "getSpace", "callManager", "useCapability", "ThreadCapabilities", "CallManager", "attendableId", "Obj", "getDXN", "toString", "undefined", "failUndefined", "identity", "useIdentity", "isNamed", "profile", "displayName", "joinSound", "useSoundEffect", "leaveSound", "extensions", "useCapabilities", "CallExtension", "useEffect", "ctx", "Context", "left", "on", "forEach", "extension", "onLeave", "callStateUpdated", "state", "onCallStateUpdated", "mediaStateUpdated", "onMediaStateUpdated", "dispose", "handleJoin", "useCallback", "joined", "leave", "play", "setRoomId", "join", "Promise", "all", "map", "onJoin", "err", "log", "catch", "handleLeave", "turnAudioOff", "turnVideoOff", "turnScreenshareOff", "isJoined", "React", "StackItem", "Content", "classNames", "toolbar", "DisplayNameMissing", "Call", "Root", "Grid", "Toolbar", "defaultThread", "target", "ChannelToolbar", "onJoinCall", "ChatContainer", "thread", "t", "useTranslation", "meta", "id", "client", "useClient", "setDisplayName", "useState", "handleChange", "event", "value", "handleSave", "halo", "updateProfile", "ControlGroup", "ControlItemInput", "title", "description", "Input", "TextInput", "onChange", "placeholder", "ControlGroupButton", "disabled", "onClick", "useChannelToolbarActions", "creator", "useMemo", "Atom", "make", "nodes", "createMenuItemGroup", "label", "ns", "createMenuAction", "icon", "type", "edges", "source", "useMenuActions", "menuProps", "ElevationProvider", "elevation", "MenuProvider", "ToolbarMenu", "textBlockWidth"]
|
|
7
|
+
}
|
|
@@ -21,7 +21,7 @@ var createBlackCanvasStreamTrack = async ({ ctx, width, height }) => {
|
|
|
21
21
|
canvasCtx.fillStyle = "black";
|
|
22
22
|
canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
|
|
23
23
|
};
|
|
24
|
-
scheduleTaskInterval(ctx, async () => drawFrame(),
|
|
24
|
+
scheduleTaskInterval(ctx, async () => drawFrame(), 200);
|
|
25
25
|
const track = canvas.captureStream().getVideoTracks()[0];
|
|
26
26
|
drawFrame();
|
|
27
27
|
await cancelWithContext(ctx, waitForCondition({
|
|
@@ -30,18 +30,68 @@ var createBlackCanvasStreamTrack = async ({ ctx, width, height }) => {
|
|
|
30
30
|
}));
|
|
31
31
|
return track;
|
|
32
32
|
};
|
|
33
|
+
var audioContextStartedPreviously = false;
|
|
34
|
+
var userGestureEvents = [
|
|
35
|
+
"click",
|
|
36
|
+
"contextmenu",
|
|
37
|
+
"auxclick",
|
|
38
|
+
"dblclick",
|
|
39
|
+
"mousedown",
|
|
40
|
+
"mouseup",
|
|
41
|
+
"pointerup",
|
|
42
|
+
"touchend",
|
|
43
|
+
"keydown",
|
|
44
|
+
"keyup"
|
|
45
|
+
];
|
|
33
46
|
var createInaudibleAudioStreamTrack = async ({ ctx }) => {
|
|
34
47
|
const audioContext = new window.AudioContext();
|
|
35
48
|
const oscillator = audioContext.createOscillator();
|
|
36
49
|
oscillator.type = "triangle";
|
|
37
50
|
oscillator.frequency.setValueAtTime(20, audioContext.currentTime);
|
|
38
51
|
const gainNode = audioContext.createGain();
|
|
39
|
-
gainNode.gain.setValueAtTime(0
|
|
52
|
+
gainNode.gain.setValueAtTime(0, audioContext.currentTime);
|
|
40
53
|
oscillator.connect(gainNode);
|
|
41
54
|
const destination = audioContext.createMediaStreamDestination();
|
|
42
55
|
gainNode.connect(destination);
|
|
43
|
-
|
|
56
|
+
let oscillatorStarted = false;
|
|
57
|
+
const ensureOscillatorStarted = () => {
|
|
58
|
+
if (oscillatorStarted) return;
|
|
59
|
+
oscillator.start();
|
|
60
|
+
oscillatorStarted = true;
|
|
61
|
+
};
|
|
62
|
+
const stateChangeHandler = () => {
|
|
63
|
+
if (audioContext.state === "running") {
|
|
64
|
+
audioContextStartedPreviously = true;
|
|
65
|
+
ensureOscillatorStarted();
|
|
66
|
+
}
|
|
67
|
+
if (audioContext.state === "suspended" || audioContext.state === "interrupted") {
|
|
68
|
+
resumeAudioContext();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
audioContext.addEventListener("statechange", stateChangeHandler);
|
|
72
|
+
const resumeAudioContext = () => {
|
|
73
|
+
void audioContext.resume().then(() => {
|
|
74
|
+
cleanUpUserGestureListeners();
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
const cleanUpUserGestureListeners = () => {
|
|
78
|
+
userGestureEvents.forEach((gesture) => {
|
|
79
|
+
document.removeEventListener(gesture, resumeAudioContext, {
|
|
80
|
+
capture: true
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
if (audioContextStartedPreviously) {
|
|
85
|
+
resumeAudioContext();
|
|
86
|
+
} else {
|
|
87
|
+
userGestureEvents.forEach((gesture) => {
|
|
88
|
+
document.addEventListener(gesture, resumeAudioContext, {
|
|
89
|
+
capture: true
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
44
93
|
ctx.onDispose(async () => {
|
|
94
|
+
cleanUpUserGestureListeners();
|
|
45
95
|
oscillator.disconnect();
|
|
46
96
|
oscillator.stop();
|
|
47
97
|
await audioContext.close();
|
|
@@ -53,4 +103,4 @@ export {
|
|
|
53
103
|
createBlackCanvasStreamTrack,
|
|
54
104
|
createInaudibleAudioStreamTrack
|
|
55
105
|
};
|
|
56
|
-
//# sourceMappingURL=chunk-
|
|
106
|
+
//# sourceMappingURL=chunk-ISCHODBV.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/calls/util/stub-media-streams.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n//\n\nimport { scheduleTaskInterval, waitForCondition } from '@dxos/async';\nimport { type Context, cancelWithContext } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\n\n/**\n * Creates a black canvas stream track.\n * We need this to to have black rectangle video that is live (have frames) when video feed is disabled.\n */\nexport const createBlackCanvasStreamTrack = async ({\n ctx,\n width,\n height,\n}: {\n ctx: Context;\n width: number;\n height: number;\n}): Promise<MediaStreamTrack> => {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n\n const canvasCtx = canvas.getContext('2d');\n invariant(canvasCtx);\n const drawFrame = () => {\n canvasCtx.fillStyle = 'black';\n canvasCtx.fillRect(0, 0, canvas.width, canvas.height);\n };\n scheduleTaskInterval(ctx, async () => drawFrame(), 200);\n\n const track = canvas.captureStream().getVideoTracks()[0];\n drawFrame();\n\n await cancelWithContext(ctx, waitForCondition({ condition: () => track.readyState === 'live', timeout: 1_000 }));\n\n return track;\n};\n\nlet audioContextStartedPreviously = false;\nconst userGestureEvents = [\n 'click',\n 'contextmenu',\n 'auxclick',\n 'dblclick',\n 'mousedown',\n 'mouseup',\n 'pointerup',\n 'touchend',\n 'keydown',\n 'keyup',\n];\n\n/**\n * Creates an inaudible audio stream track.\n * We need this to have audio track available when audio is disabled.\n */\nexport const createInaudibleAudioStreamTrack = async ({ ctx }: { ctx: Context }): Promise<MediaStreamTrack> => {\n const audioContext = new window.AudioContext();\n\n const oscillator = audioContext.createOscillator();\n oscillator.type = 'triangle';\n oscillator.frequency.setValueAtTime(20, audioContext.currentTime);\n\n const gainNode = audioContext.createGain();\n gainNode.gain.setValueAtTime(0, audioContext.currentTime);\n oscillator.connect(gainNode);\n\n const destination = audioContext.createMediaStreamDestination();\n gainNode.connect(destination);\n\n let oscillatorStarted = false;\n const ensureOscillatorStarted = () => {\n if (oscillatorStarted) return;\n oscillator.start();\n oscillatorStarted = true;\n };\n\n const stateChangeHandler = () => {\n if (audioContext.state === 'running') {\n audioContextStartedPreviously = true;\n ensureOscillatorStarted();\n }\n\n if (audioContext.state === 'suspended' || (audioContext.state as string) === 'interrupted') {\n resumeAudioContext();\n }\n };\n\n audioContext.addEventListener('statechange', stateChangeHandler);\n\n const resumeAudioContext = () => {\n void audioContext.resume().then(() => {\n cleanUpUserGestureListeners();\n });\n };\n\n const cleanUpUserGestureListeners = () => {\n userGestureEvents.forEach((gesture) => {\n document.removeEventListener(gesture, resumeAudioContext, {\n capture: true,\n });\n });\n };\n\n if (audioContextStartedPreviously) {\n resumeAudioContext();\n } else {\n userGestureEvents.forEach((gesture) => {\n document.addEventListener(gesture, resumeAudioContext, {\n capture: true,\n });\n });\n }\n\n ctx.onDispose(async () => {\n cleanUpUserGestureListeners();\n oscillator.disconnect();\n oscillator.stop();\n await audioContext.close();\n });\n\n return destination.stream.getAudioTracks()[0];\n};\n"],
|
|
5
|
+
"mappings": ";AAKA,SAASA,sBAAsBC,wBAAwB;AACvD,SAAuBC,yBAAyB;AAChD,SAASC,iBAAiB;;AAMnB,IAAMC,+BAA+B,OAAO,EACjDC,KACAC,OACAC,OAAM,MAKP;AACC,QAAMC,SAASC,SAASC,cAAc,QAAA;AACtCF,SAAOF,QAAQA;AACfE,SAAOD,SAASA;AAEhB,QAAMI,YAAYH,OAAOI,WAAW,IAAA;AACpCT,YAAUQ,WAAAA,QAAAA;;;;;;;;;AACV,QAAME,YAAY,MAAA;AAChBF,cAAUG,YAAY;AACtBH,cAAUI,SAAS,GAAG,GAAGP,OAAOF,OAAOE,OAAOD,MAAM;EACtD;AACAP,uBAAqBK,KAAK,YAAYQ,UAAAA,GAAa,GAAA;AAEnD,QAAMG,QAAQR,OAAOS,cAAa,EAAGC,eAAc,EAAG,CAAA;AACtDL,YAAAA;AAEA,QAAMX,kBAAkBG,KAAKJ,iBAAiB;IAAEkB,WAAW,MAAMH,MAAMI,eAAe;IAAQC,SAAS;EAAM,CAAA,CAAA;AAE7G,SAAOL;AACT;AAEA,IAAIM,gCAAgC;AACpC,IAAMC,oBAAoB;EACxB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAOK,IAAMC,kCAAkC,OAAO,EAAEnB,IAAG,MAAoB;AAC7E,QAAMoB,eAAe,IAAIC,OAAOC,aAAY;AAE5C,QAAMC,aAAaH,aAAaI,iBAAgB;AAChDD,aAAWE,OAAO;AAClBF,aAAWG,UAAUC,eAAe,IAAIP,aAAaQ,WAAW;AAEhE,QAAMC,WAAWT,aAAaU,WAAU;AACxCD,WAASE,KAAKJ,eAAe,GAAGP,aAAaQ,WAAW;AACxDL,aAAWS,QAAQH,QAAAA;AAEnB,QAAMI,cAAcb,aAAac,6BAA4B;AAC7DL,WAASG,QAAQC,WAAAA;AAEjB,MAAIE,oBAAoB;AACxB,QAAMC,0BAA0B,MAAA;AAC9B,QAAID,kBAAmB;AACvBZ,eAAWc,MAAK;AAChBF,wBAAoB;EACtB;AAEA,QAAMG,qBAAqB,MAAA;AACzB,QAAIlB,aAAamB,UAAU,WAAW;AACpCtB,sCAAgC;AAChCmB,8BAAAA;IACF;AAEA,QAAIhB,aAAamB,UAAU,eAAgBnB,aAAamB,UAAqB,eAAe;AAC1FC,yBAAAA;IACF;EACF;AAEApB,eAAaqB,iBAAiB,eAAeH,kBAAAA;AAE7C,QAAME,qBAAqB,MAAA;AACzB,SAAKpB,aAAasB,OAAM,EAAGC,KAAK,MAAA;AAC9BC,kCAAAA;IACF,CAAA;EACF;AAEA,QAAMA,8BAA8B,MAAA;AAClC1B,sBAAkB2B,QAAQ,CAACC,YAAAA;AACzB1C,eAAS2C,oBAAoBD,SAASN,oBAAoB;QACxDQ,SAAS;MACX,CAAA;IACF,CAAA;EACF;AAEA,MAAI/B,+BAA+B;AACjCuB,uBAAAA;EACF,OAAO;AACLtB,sBAAkB2B,QAAQ,CAACC,YAAAA;AACzB1C,eAASqC,iBAAiBK,SAASN,oBAAoB;QACrDQ,SAAS;MACX,CAAA;IACF,CAAA;EACF;AAEAhD,MAAIiD,UAAU,YAAA;AACZL,gCAAAA;AACArB,eAAW2B,WAAU;AACrB3B,eAAW4B,KAAI;AACf,UAAM/B,aAAagC,MAAK;EAC1B,CAAA;AAEA,SAAOnB,YAAYoB,OAAOC,eAAc,EAAG,CAAA;AAC7C;",
|
|
6
|
+
"names": ["scheduleTaskInterval", "waitForCondition", "cancelWithContext", "invariant", "createBlackCanvasStreamTrack", "ctx", "width", "height", "canvas", "document", "createElement", "canvasCtx", "getContext", "drawFrame", "fillStyle", "fillRect", "track", "captureStream", "getVideoTracks", "condition", "readyState", "timeout", "audioContextStartedPreviously", "userGestureEvents", "createInaudibleAudioStreamTrack", "audioContext", "window", "AudioContext", "oscillator", "createOscillator", "type", "frequency", "setValueAtTime", "currentTime", "gainNode", "createGain", "gain", "connect", "destination", "createMediaStreamDestination", "oscillatorStarted", "ensureOscillatorStarted", "start", "stateChangeHandler", "state", "resumeAudioContext", "addEventListener", "resume", "then", "cleanUpUserGestureListeners", "forEach", "gesture", "removeEventListener", "capture", "onDispose", "disconnect", "stop", "close", "stream", "getAudioTracks"]
|
|
7
|
+
}
|