@dxos/plugin-thread 0.8.4-main.f5c0578 → 0.8.4-main.fcfe5033a5
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/add-message-VPPFFLFL.mjs +97 -0
- package/dist/lib/browser/add-message-VPPFFLFL.mjs.map +7 -0
- package/dist/lib/browser/blueprints/index.mjs +37 -0
- package/dist/lib/browser/blueprints/index.mjs.map +7 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/browser/chunk-MESW3R4Q.mjs +61 -0
- package/dist/lib/browser/chunk-MESW3R4Q.mjs.map +7 -0
- package/dist/lib/browser/chunk-VPM44Z35.mjs +259 -0
- package/dist/lib/browser/chunk-VPM44Z35.mjs.map +7 -0
- package/dist/lib/browser/create-OQKG4S47.mjs +55 -0
- package/dist/lib/browser/create-OQKG4S47.mjs.map +7 -0
- package/dist/lib/browser/create-channel-EF67LCS6.mjs +21 -0
- package/dist/lib/browser/create-channel-EF67LCS6.mjs.map +7 -0
- package/dist/lib/browser/create-channel-thread-CCZTSWQ6.mjs +28 -0
- package/dist/lib/browser/create-channel-thread-CCZTSWQ6.mjs.map +7 -0
- package/dist/lib/browser/create-proposals-CMK7S7VS.mjs +57 -0
- package/dist/lib/browser/create-proposals-CMK7S7VS.mjs.map +7 -0
- package/dist/lib/browser/delete-FSFVU6ZA.mjs +59 -0
- package/dist/lib/browser/delete-FSFVU6ZA.mjs.map +7 -0
- package/dist/lib/browser/delete-message-XL5M5J33.mjs +64 -0
- package/dist/lib/browser/delete-message-XL5M5J33.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +2253 -221
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/on-create-space-VYS2JGVT.mjs +25 -0
- package/dist/lib/browser/on-create-space-VYS2JGVT.mjs.map +7 -0
- package/dist/lib/browser/operations/index.mjs +14 -0
- package/dist/lib/browser/operations/index.mjs.map +7 -0
- package/dist/lib/browser/restore-2ZGMKUSD.mjs +33 -0
- package/dist/lib/browser/restore-2ZGMKUSD.mjs.map +7 -0
- package/dist/lib/browser/restore-message-OYEGWPII.mjs +42 -0
- package/dist/lib/browser/restore-message-OYEGWPII.mjs.map +7 -0
- package/dist/lib/browser/select-VG2XLULE.mjs +26 -0
- package/dist/lib/browser/select-VG2XLULE.mjs.map +7 -0
- package/dist/lib/browser/toggle-resolved-MM6YC5BU.mjs +45 -0
- package/dist/lib/browser/toggle-resolved-MM6YC5BU.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +8 -12
- package/dist/lib/node-esm/add-message-XWKHLNS6.mjs +98 -0
- package/dist/lib/node-esm/add-message-XWKHLNS6.mjs.map +7 -0
- package/dist/lib/node-esm/blueprints/index.mjs +38 -0
- package/dist/lib/node-esm/blueprints/index.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
- package/dist/lib/node-esm/chunk-JTHXNWKJ.mjs +260 -0
- package/dist/lib/node-esm/chunk-JTHXNWKJ.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-SDRAQNSQ.mjs +62 -0
- package/dist/lib/node-esm/chunk-SDRAQNSQ.mjs.map +7 -0
- package/dist/lib/node-esm/create-6ZOFMMYA.mjs +56 -0
- package/dist/lib/node-esm/create-6ZOFMMYA.mjs.map +7 -0
- package/dist/lib/node-esm/create-channel-UYWUNB3L.mjs +22 -0
- package/dist/lib/node-esm/create-channel-UYWUNB3L.mjs.map +7 -0
- package/dist/lib/node-esm/create-channel-thread-UQF2SBHS.mjs +29 -0
- package/dist/lib/node-esm/create-channel-thread-UQF2SBHS.mjs.map +7 -0
- package/dist/lib/node-esm/create-proposals-5FJNURKH.mjs +58 -0
- package/dist/lib/node-esm/create-proposals-5FJNURKH.mjs.map +7 -0
- package/dist/lib/node-esm/delete-WRODXR3E.mjs +60 -0
- package/dist/lib/node-esm/delete-WRODXR3E.mjs.map +7 -0
- package/dist/lib/node-esm/delete-message-TAHCYTW2.mjs +65 -0
- package/dist/lib/node-esm/delete-message-TAHCYTW2.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +2253 -221
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/on-create-space-XDY2YXPV.mjs +26 -0
- package/dist/lib/node-esm/on-create-space-XDY2YXPV.mjs.map +7 -0
- package/dist/lib/node-esm/operations/index.mjs +15 -0
- package/dist/lib/node-esm/operations/index.mjs.map +7 -0
- package/dist/lib/node-esm/restore-T3QA7TSL.mjs +34 -0
- package/dist/lib/node-esm/restore-T3QA7TSL.mjs.map +7 -0
- package/dist/lib/node-esm/restore-message-WFTEVBEV.mjs +43 -0
- package/dist/lib/node-esm/restore-message-WFTEVBEV.mjs.map +7 -0
- package/dist/lib/node-esm/select-Q4UDWJJF.mjs +27 -0
- package/dist/lib/node-esm/select-Q4UDWJJF.mjs.map +7 -0
- package/dist/lib/node-esm/toggle-resolved-33XTAK2H.mjs +46 -0
- package/dist/lib/node-esm/toggle-resolved-33XTAK2H.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +8 -12
- package/dist/types/src/ThreadPlugin.d.ts +2 -1
- package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
- package/dist/types/src/blueprints/index.d.ts +2 -0
- package/dist/types/src/blueprints/index.d.ts.map +1 -0
- package/dist/types/src/blueprints/thread-blueprint.d.ts +4 -0
- package/dist/types/src/blueprints/thread-blueprint.d.ts.map +1 -0
- package/dist/types/src/calls/call-manager.d.ts +40 -30
- package/dist/types/src/calls/call-manager.d.ts.map +1 -1
- package/dist/types/src/calls/call-swarm-synchronizer.d.ts +2 -2
- package/dist/types/src/calls/call-swarm-synchronizer.d.ts.map +1 -1
- package/dist/types/src/calls/media-manager.d.ts +2 -2
- 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 +4 -2
- 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/util/task-scheduling.d.ts +2 -2
- package/dist/types/src/calls/util/task-scheduling.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 +4 -2
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/blueprint-definition.d.ts +6 -0
- package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -0
- package/dist/types/src/capabilities/call-manager.d.ts +3 -2
- package/dist/types/src/capabilities/call-manager.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +13 -13
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/markdown.d.ts +3 -2
- package/dist/types/src/capabilities/markdown.d.ts.map +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
- package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-root.d.ts +4 -2
- package/dist/types/src/capabilities/react-root.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +3 -2
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/settings.d.ts +5 -2
- package/dist/types/src/capabilities/settings.d.ts.map +1 -1
- package/dist/types/src/capabilities/state.d.ts +5 -5
- package/dist/types/src/capabilities/state.d.ts.map +1 -1
- package/dist/types/src/capabilities/undo-mappings.d.ts +5 -0
- package/dist/types/src/capabilities/undo-mappings.d.ts.map +1 -0
- package/dist/types/src/components/Call/Call.d.ts.map +1 -1
- 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/CommentsPanel/CommentsPanel.d.ts +13 -0
- package/dist/types/src/components/CommentsPanel/CommentsPanel.d.ts.map +1 -0
- package/dist/types/src/components/CommentsPanel/CommentsPanel.stories.d.ts +160 -0
- package/dist/types/src/components/CommentsPanel/CommentsPanel.stories.d.ts.map +1 -0
- package/dist/types/src/components/CommentsPanel/CommentsThread.d.ts +14 -0
- package/dist/types/src/components/CommentsPanel/CommentsThread.d.ts.map +1 -0
- package/dist/types/src/components/CommentsPanel/index.d.ts +3 -0
- package/dist/types/src/components/CommentsPanel/index.d.ts.map +1 -0
- package/dist/types/src/components/Lobby/Lobby.d.ts.map +1 -1
- package/dist/types/src/components/Media/VideoObject.d.ts +3 -3
- 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/MessagePanel/MessagePanel.d.ts +15 -0
- package/dist/types/src/components/MessagePanel/MessagePanel.d.ts.map +1 -0
- package/dist/types/src/components/MessagePanel/index.d.ts +2 -0
- package/dist/types/src/components/MessagePanel/index.d.ts.map +1 -0
- package/dist/types/src/components/Participant/Participant.d.ts.map +1 -1
- package/dist/types/src/components/Participant/ParticipantGrid.d.ts.map +1 -1
- package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.d.ts.map +1 -1
- package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts +160 -5
- 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/ResponsiveGrid/{ResponsiveContainer.d.ts → ResponsivePanel.d.ts} +4 -4
- package/dist/types/src/components/ResponsiveGrid/ResponsivePanel.d.ts.map +1 -0
- package/dist/types/src/components/ResponsiveGrid/ResponsivePanel.stories.d.ts +164 -0
- package/dist/types/src/components/ResponsiveGrid/ResponsivePanel.stories.d.ts.map +1 -0
- package/dist/types/src/components/ResponsiveGrid/index.d.ts +1 -1
- package/dist/types/src/components/ResponsiveGrid/index.d.ts.map +1 -1
- package/dist/types/src/components/ThreadSettings/ThreadSettings.d.ts +6 -0
- package/dist/types/src/components/ThreadSettings/ThreadSettings.d.ts.map +1 -0
- package/dist/types/src/components/ThreadSettings/ThreadSettings.stories.d.ts +161 -0
- package/dist/types/src/components/ThreadSettings/ThreadSettings.stories.d.ts.map +1 -0
- package/dist/types/src/components/ThreadSettings/index.d.ts +2 -0
- package/dist/types/src/components/ThreadSettings/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +4 -9
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/containers/CallDebugPanel/CallDebugPanel.d.ts +15 -0
- package/dist/types/src/containers/CallDebugPanel/CallDebugPanel.d.ts.map +1 -0
- package/dist/types/src/containers/CallDebugPanel/index.d.ts +2 -0
- package/dist/types/src/containers/CallDebugPanel/index.d.ts.map +1 -0
- package/dist/types/src/{components → containers/CallSidebar}/CallSidebar.d.ts +0 -1
- package/dist/types/src/containers/CallSidebar/CallSidebar.d.ts.map +1 -0
- package/dist/types/src/containers/CallSidebar/index.d.ts +2 -0
- package/dist/types/src/containers/CallSidebar/index.d.ts.map +1 -0
- package/dist/types/src/containers/ChannelContainer/ChannelContainer.d.ts +12 -0
- package/dist/types/src/containers/ChannelContainer/ChannelContainer.d.ts.map +1 -0
- package/dist/types/src/containers/ChannelContainer/ChannelContainer.stories.d.ts +162 -0
- package/dist/types/src/containers/ChannelContainer/ChannelContainer.stories.d.ts.map +1 -0
- package/dist/types/src/containers/ChannelContainer/index.d.ts +2 -0
- package/dist/types/src/containers/ChannelContainer/index.d.ts.map +1 -0
- package/dist/types/src/containers/ChatContainer/ChatContainer.d.ts +16 -0
- package/dist/types/src/containers/ChatContainer/ChatContainer.d.ts.map +1 -0
- package/dist/types/src/containers/ChatContainer/ChatContainer.stories.d.ts +162 -0
- package/dist/types/src/containers/ChatContainer/ChatContainer.stories.d.ts.map +1 -0
- package/dist/types/src/containers/ChatContainer/index.d.ts +4 -0
- package/dist/types/src/containers/ChatContainer/index.d.ts.map +1 -0
- package/dist/types/src/containers/ThreadCompanion/ThreadCompanion.d.ts +8 -0
- package/dist/types/src/containers/ThreadCompanion/ThreadCompanion.d.ts.map +1 -0
- package/dist/types/src/containers/ThreadCompanion/index.d.ts +2 -0
- package/dist/types/src/containers/ThreadCompanion/index.d.ts.map +1 -0
- package/dist/types/src/containers/index.d.ts +7 -0
- package/dist/types/src/containers/index.d.ts.map +1 -0
- package/dist/types/src/{components/command-extension.d.ts → extensions/command.d.ts} +1 -1
- package/dist/types/src/extensions/command.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +1 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/threads.d.ts +8 -3
- package/dist/types/src/extensions/threads.d.ts.map +1 -1
- package/dist/types/src/hooks/analytics.d.ts +2 -3
- 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/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +3 -4
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/operations/add-message.d.ts +5 -0
- package/dist/types/src/operations/add-message.d.ts.map +1 -0
- package/dist/types/src/operations/create-channel-thread.d.ts +5 -0
- package/dist/types/src/operations/create-channel-thread.d.ts.map +1 -0
- package/dist/types/src/operations/create-channel.d.ts +5 -0
- package/dist/types/src/operations/create-channel.d.ts.map +1 -0
- package/dist/types/src/operations/create-proposals.d.ts +5 -0
- package/dist/types/src/operations/create-proposals.d.ts.map +1 -0
- package/dist/types/src/operations/create.d.ts +5 -0
- package/dist/types/src/operations/create.d.ts.map +1 -0
- package/dist/types/src/operations/definitions.d.ts +2804 -0
- package/dist/types/src/operations/definitions.d.ts.map +1 -0
- package/dist/types/src/operations/delete-message.d.ts +5 -0
- package/dist/types/src/operations/delete-message.d.ts.map +1 -0
- package/dist/types/src/operations/delete.d.ts +5 -0
- package/dist/types/src/operations/delete.d.ts.map +1 -0
- package/dist/types/src/operations/index.d.ts +4 -0
- package/dist/types/src/operations/index.d.ts.map +1 -0
- package/dist/types/src/operations/on-create-space.d.ts +5 -0
- package/dist/types/src/operations/on-create-space.d.ts.map +1 -0
- package/dist/types/src/operations/restore-message.d.ts +5 -0
- package/dist/types/src/operations/restore-message.d.ts.map +1 -0
- package/dist/types/src/operations/restore.d.ts +5 -0
- package/dist/types/src/operations/restore.d.ts.map +1 -0
- package/dist/types/src/operations/select.d.ts +5 -0
- package/dist/types/src/operations/select.d.ts.map +1 -0
- package/dist/types/src/operations/toggle-resolved.d.ts +5 -0
- package/dist/types/src/operations/toggle-resolved.d.ts.map +1 -0
- package/dist/types/src/testing/data.d.ts +5 -0
- package/dist/types/src/testing/data.d.ts.map +1 -0
- package/dist/types/src/testing/stories.d.ts +2 -1
- package/dist/types/src/testing/stories.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +142 -72
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Channel.d.ts +715 -0
- package/dist/types/src/types/Channel.d.ts.map +1 -0
- package/dist/types/src/types/Settings.d.ts +5 -0
- package/dist/types/src/types/Settings.d.ts.map +1 -0
- package/dist/types/src/types/capabilities.d.ts +24 -0
- package/dist/types/src/types/capabilities.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +2 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +4 -374
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +112 -67
- package/src/ThreadPlugin.tsx +108 -132
- package/src/blueprints/index.ts +5 -0
- package/src/blueprints/thread-blueprint.ts +37 -0
- package/src/calls/call-manager.ts +77 -53
- package/src/calls/call-swarm-synchronizer.ts +2 -2
- package/src/calls/media-manager.ts +65 -36
- package/src/calls/types.ts +7 -3
- package/src/calls/util/calls-service.ts +62 -13
- package/src/calls/util/stub-media-streams.ts +62 -5
- package/src/calls/util/task-scheduling.ts +4 -4
- package/src/calls-service.stories.tsx +79 -65
- package/src/capabilities/app-graph-builder.ts +175 -163
- package/src/capabilities/blueprint-definition.ts +17 -0
- package/src/capabilities/call-manager.ts +19 -12
- package/src/capabilities/index.ts +15 -11
- package/src/capabilities/markdown.ts +50 -37
- package/src/capabilities/operation-handler.ts +16 -0
- package/src/capabilities/react-root.tsx +12 -9
- package/src/capabilities/react-surface.tsx +80 -78
- package/src/capabilities/settings.ts +28 -12
- package/src/capabilities/state.ts +14 -18
- package/src/capabilities/undo-mappings.ts +46 -0
- package/src/components/Call/Call.tsx +11 -7
- package/src/components/Call/Toolbar.tsx +61 -44
- package/src/components/CommentsPanel/CommentsPanel.stories.tsx +93 -0
- package/src/components/CommentsPanel/CommentsPanel.tsx +71 -0
- package/src/components/{CommentsThreadContainer.tsx → CommentsPanel/CommentsThread.tsx} +66 -62
- package/src/components/CommentsPanel/index.ts +6 -0
- package/src/components/Lobby/Lobby.tsx +15 -12
- package/src/components/Media/AudioStream.tsx +2 -2
- package/src/components/Media/VideoObject.stories.tsx +37 -31
- package/src/components/Media/VideoObject.tsx +1 -1
- package/src/components/MessagePanel/MessagePanel.tsx +222 -0
- package/src/components/MessagePanel/index.ts +5 -0
- package/src/components/Participant/Participant.tsx +35 -15
- package/src/components/Participant/ParticipantGrid.tsx +0 -1
- package/src/components/ResponsiveGrid/ResponsiveGrid.stories.tsx +48 -48
- package/src/components/ResponsiveGrid/ResponsiveGrid.tsx +5 -5
- package/src/components/ResponsiveGrid/ResponsiveGridItem.tsx +12 -9
- package/src/components/ResponsiveGrid/{ResponsiveContainer.stories.tsx → ResponsivePanel.stories.tsx} +9 -11
- package/src/components/ResponsiveGrid/{ResponsiveContainer.tsx → ResponsivePanel.tsx} +5 -5
- package/src/components/ResponsiveGrid/index.ts +1 -1
- package/src/components/ThreadSettings/ThreadSettings.stories.tsx +31 -0
- package/src/components/ThreadSettings/ThreadSettings.tsx +20 -0
- package/src/components/ThreadSettings/index.ts +5 -0
- package/src/components/index.ts +5 -12
- package/src/containers/CallDebugPanel/CallDebugPanel.tsx +173 -0
- package/src/containers/CallDebugPanel/index.ts +5 -0
- package/src/containers/CallSidebar/CallSidebar.tsx +18 -0
- package/src/containers/CallSidebar/index.ts +5 -0
- package/src/containers/ChannelContainer/ChannelContainer.stories.tsx +61 -0
- package/src/{components → containers/ChannelContainer}/ChannelContainer.tsx +93 -71
- package/src/containers/ChannelContainer/index.ts +5 -0
- package/src/containers/ChatContainer/ChatContainer.stories.tsx +87 -0
- package/src/containers/ChatContainer/ChatContainer.tsx +131 -0
- package/src/containers/ChatContainer/index.ts +8 -0
- package/src/containers/ThreadCompanion/ThreadCompanion.tsx +217 -0
- package/src/containers/ThreadCompanion/index.ts +5 -0
- package/src/containers/index.ts +11 -0
- package/src/{components/command-extension.ts → extensions/command.ts} +6 -3
- package/src/extensions/index.ts +1 -0
- package/src/extensions/threads.ts +87 -42
- package/src/hooks/analytics.ts +22 -21
- package/src/hooks/index.ts +3 -1
- package/src/hooks/useBlackCanvasStreamTrack.tsx +27 -0
- package/src/hooks/useVideoStreamTrack.tsx +6 -3
- package/src/index.ts +1 -1
- package/src/meta.ts +11 -7
- package/src/operations/add-message.ts +81 -0
- package/src/operations/create-channel-thread.ts +26 -0
- package/src/operations/create-channel.ts +20 -0
- package/src/operations/create-proposals.ts +49 -0
- package/src/operations/create.ts +48 -0
- package/src/operations/definitions.ts +177 -0
- package/src/operations/delete-message.ts +53 -0
- package/src/operations/delete.ts +63 -0
- package/src/operations/index.ts +22 -0
- package/src/operations/on-create-space.ts +27 -0
- package/src/operations/restore-message.ts +38 -0
- package/src/operations/restore.ts +38 -0
- package/src/operations/select.ts +24 -0
- package/src/operations/toggle-resolved.ts +41 -0
- package/src/testing/data.ts +49 -0
- package/src/testing/stories.ts +18 -21
- package/src/translations.ts +74 -73
- package/src/types/Channel.ts +37 -0
- package/src/types/Settings.ts +10 -0
- package/src/types/capabilities.ts +36 -0
- package/src/types/index.ts +2 -1
- package/src/types/types.ts +5 -100
- package/src/typings/peermetrics-webrtc-stats.d.ts +17 -1
- package/src/util.ts +2 -2
- 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 +0 -171
- package/dist/lib/browser/app-graph-builder-AF3M7UWN.mjs.map +0 -7
- package/dist/lib/browser/call-manager-XRRCAVLI.mjs +0 -24
- package/dist/lib/browser/call-manager-XRRCAVLI.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 +0 -31
- 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 +0 -56
- package/dist/lib/browser/chunk-JGKMMI65.mjs.map +0 -7
- package/dist/lib/browser/chunk-TUFWPOVS.mjs +0 -1698
- package/dist/lib/browser/chunk-TUFWPOVS.mjs.map +0 -7
- package/dist/lib/browser/chunk-X5PIP5YR.mjs +0 -149
- package/dist/lib/browser/chunk-X5PIP5YR.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZJ7QBXK6.mjs +0 -984
- package/dist/lib/browser/chunk-ZJ7QBXK6.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-DCY4P4OX.mjs +0 -369
- package/dist/lib/browser/intent-resolver-DCY4P4OX.mjs.map +0 -7
- package/dist/lib/browser/markdown-WZSXCEZJ.mjs +0 -169
- 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 +0 -109
- package/dist/lib/browser/react-surface-PYAMIADB.mjs.map +0 -7
- package/dist/lib/browser/settings-AC6YSASL.mjs +0 -22
- package/dist/lib/browser/settings-AC6YSASL.mjs.map +0 -7
- package/dist/lib/browser/state-2T4KDWBX.mjs +0 -34
- package/dist/lib/browser/state-2T4KDWBX.mjs.map +0 -7
- package/dist/lib/node-esm/ChannelContainer-B2ZGAE4P.mjs +0 -17
- package/dist/lib/node-esm/ChannelContainer-B2ZGAE4P.mjs.map +0 -7
- package/dist/lib/node-esm/ChatContainer-2CT4PJ7I.mjs +0 -16
- package/dist/lib/node-esm/ChatContainer-2CT4PJ7I.mjs.map +0 -7
- package/dist/lib/node-esm/app-graph-builder-OLSJVCWY.mjs +0 -172
- package/dist/lib/node-esm/app-graph-builder-OLSJVCWY.mjs.map +0 -7
- package/dist/lib/node-esm/call-manager-EI7FXRAU.mjs +0 -25
- package/dist/lib/node-esm/call-manager-EI7FXRAU.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-4TME3BR4.mjs +0 -1699
- package/dist/lib/node-esm/chunk-4TME3BR4.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-57XR3LEF.mjs +0 -33
- 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 +0 -58
- package/dist/lib/node-esm/chunk-QBHKLWGR.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-SED3O2XO.mjs +0 -150
- 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 +0 -985
- package/dist/lib/node-esm/chunk-YIDU3DXK.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-QGTPU6QB.mjs +0 -370
- package/dist/lib/node-esm/intent-resolver-QGTPU6QB.mjs.map +0 -7
- package/dist/lib/node-esm/markdown-3MZXUGUA.mjs +0 -170
- 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 +0 -110
- package/dist/lib/node-esm/react-surface-UJFCSFNO.mjs.map +0 -7
- package/dist/lib/node-esm/settings-N52O7MLS.mjs +0 -23
- package/dist/lib/node-esm/settings-N52O7MLS.mjs.map +0 -7
- package/dist/lib/node-esm/state-62TQKQVB.mjs +0 -35
- package/dist/lib/node-esm/state-62TQKQVB.mjs.map +0 -7
- package/dist/types/src/capabilities/capabilities.d.ts +0 -27
- package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
- package/dist/types/src/components/CallDebugPanel.d.ts +0 -8
- package/dist/types/src/components/CallDebugPanel.d.ts.map +0 -1
- package/dist/types/src/components/CallSidebar.d.ts.map +0 -1
- package/dist/types/src/components/ChannelContainer.d.ts +0 -14
- package/dist/types/src/components/ChannelContainer.d.ts.map +0 -1
- package/dist/types/src/components/ChannelContainer.stories.d.ts +0 -10
- package/dist/types/src/components/ChannelContainer.stories.d.ts.map +0 -1
- package/dist/types/src/components/Chat.stories.d.ts +0 -7
- package/dist/types/src/components/Chat.stories.d.ts.map +0 -1
- package/dist/types/src/components/ChatContainer.d.ts +0 -17
- package/dist/types/src/components/ChatContainer.d.ts.map +0 -1
- package/dist/types/src/components/Comments.stories.d.ts +0 -6
- package/dist/types/src/components/Comments.stories.d.ts.map +0 -1
- package/dist/types/src/components/CommentsContainer.d.ts +0 -13
- package/dist/types/src/components/CommentsContainer.d.ts.map +0 -1
- package/dist/types/src/components/CommentsThreadContainer.d.ts +0 -14
- package/dist/types/src/components/CommentsThreadContainer.d.ts.map +0 -1
- package/dist/types/src/components/MessageContainer.d.ts +0 -11
- package/dist/types/src/components/MessageContainer.d.ts.map +0 -1
- package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.d.ts.map +0 -1
- package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts +0 -10
- package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts.map +0 -1
- 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/components/ThreadSettings.d.ts +0 -6
- package/dist/types/src/components/ThreadSettings.d.ts.map +0 -1
- package/dist/types/src/components/command-extension.d.ts.map +0 -1
- package/dist/types/src/components/testing.d.ts +0 -4
- package/dist/types/src/components/testing.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/capabilities/capabilities.ts +0 -33
- package/src/capabilities/intent-resolver.ts +0 -315
- package/src/components/CallDebugPanel.tsx +0 -115
- package/src/components/CallSidebar.tsx +0 -18
- package/src/components/ChannelContainer.stories.tsx +0 -59
- package/src/components/Chat.stories.tsx +0 -89
- package/src/components/ChatContainer.tsx +0 -142
- package/src/components/Comments.stories.tsx +0 -93
- package/src/components/CommentsContainer.tsx +0 -72
- package/src/components/MessageContainer.tsx +0 -152
- package/src/components/ThreadComplementary.tsx +0 -151
- package/src/components/ThreadSettings.tsx +0 -17
- package/src/components/testing.ts +0 -29
- package/src/types/schema.ts +0 -33
- /package/dist/lib/browser/{ChannelContainer-O2SFQJU7.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
- /package/dist/lib/{browser/ChatContainer-PVT3DUZJ.mjs.map → node-esm/chunk-HSLMI22Q.mjs.map} +0 -0
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Atom, type Registry } from '@effect-atom/atom-react';
|
|
6
6
|
|
|
7
7
|
import { Event, synchronized } from '@dxos/async';
|
|
8
8
|
import { type Client } from '@dxos/client';
|
|
9
9
|
import { Resource } from '@dxos/context';
|
|
10
10
|
import { invariant } from '@dxos/invariant';
|
|
11
|
-
import { live } from '@dxos/live-object';
|
|
12
11
|
import { type Tracks } from '@dxos/protocols/proto/dxos/edge/calls';
|
|
13
12
|
import { isNonNullable } from '@dxos/util';
|
|
14
13
|
|
|
@@ -31,84 +30,103 @@ export class CallManager extends Resource {
|
|
|
31
30
|
public readonly left = new Event<string>();
|
|
32
31
|
|
|
33
32
|
/**
|
|
34
|
-
*
|
|
33
|
+
* Atom-based state. Updated via `_updateState()`.
|
|
35
34
|
* CAUTION: Do not change directly.
|
|
36
35
|
*/
|
|
37
|
-
private readonly
|
|
36
|
+
private readonly _stateAtom = Atom.make<GlobalState>({
|
|
38
37
|
call: {},
|
|
39
38
|
media: { pulledAudioTracks: {}, pulledVideoStreams: {} },
|
|
40
39
|
});
|
|
41
40
|
|
|
42
|
-
//
|
|
43
|
-
private readonly
|
|
44
|
-
private readonly
|
|
45
|
-
private readonly
|
|
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
|
+
);
|
|
46
64
|
|
|
47
65
|
private readonly _swarmSynchronizer: CallSwarmSynchronizer;
|
|
48
66
|
private readonly _mediaManager: MediaManager;
|
|
49
67
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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;
|
|
53
75
|
}
|
|
54
76
|
|
|
55
|
-
/**
|
|
56
|
-
get
|
|
57
|
-
return this.
|
|
77
|
+
/** Derived atom for raisedHand. */
|
|
78
|
+
get raisedHandAtom(): Atom.Atom<boolean> {
|
|
79
|
+
return this._raisedHandAtom;
|
|
58
80
|
}
|
|
59
81
|
|
|
60
|
-
/**
|
|
61
|
-
get
|
|
62
|
-
return this.
|
|
82
|
+
/** Derived atom for speaking. */
|
|
83
|
+
get speakingAtom(): Atom.Atom<boolean> {
|
|
84
|
+
return this._speakingAtom;
|
|
63
85
|
}
|
|
64
86
|
|
|
65
|
-
/**
|
|
66
|
-
get
|
|
67
|
-
return this.
|
|
87
|
+
/** Derived atom for joined. */
|
|
88
|
+
get joinedAtom(): Atom.Atom<boolean> {
|
|
89
|
+
return this._joinedAtom;
|
|
68
90
|
}
|
|
69
91
|
|
|
70
|
-
/**
|
|
71
|
-
get
|
|
72
|
-
return this.
|
|
92
|
+
/** Derived atom for self. */
|
|
93
|
+
get selfAtom(): Atom.Atom<UserState> {
|
|
94
|
+
return this._selfAtom;
|
|
73
95
|
}
|
|
74
96
|
|
|
75
|
-
/**
|
|
76
|
-
get
|
|
77
|
-
return this.
|
|
97
|
+
/** Derived atom for tracks. */
|
|
98
|
+
get tracksAtom(): Atom.Atom<Tracks> {
|
|
99
|
+
return this._tracksAtom;
|
|
78
100
|
}
|
|
79
101
|
|
|
80
|
-
/**
|
|
81
|
-
get
|
|
82
|
-
return this.
|
|
102
|
+
/** Derived atom for users. */
|
|
103
|
+
get usersAtom(): Atom.Atom<UserState[]> {
|
|
104
|
+
return this._usersAtom;
|
|
83
105
|
}
|
|
84
106
|
|
|
85
|
-
/**
|
|
86
|
-
get
|
|
87
|
-
return this.
|
|
107
|
+
/** Derived atom for media. */
|
|
108
|
+
get mediaAtom(): Atom.Atom<MediaState> {
|
|
109
|
+
return this._mediaAtom;
|
|
88
110
|
}
|
|
89
111
|
|
|
90
|
-
/**
|
|
91
|
-
get
|
|
92
|
-
return
|
|
93
|
-
.map((user) => (user.tracks?.audioEnabled ? user.tracks?.audio : undefined))
|
|
94
|
-
.filter(isNonNullable)
|
|
95
|
-
.map((track) => this._state.media.pulledAudioTracks[track as EncodedTrackName]?.track)
|
|
96
|
-
.filter(isNonNullable);
|
|
112
|
+
/** Derived atom for audioTracksToPlay. */
|
|
113
|
+
get audioTracksToPlayAtom(): Atom.Atom<MediaStreamTrack[]> {
|
|
114
|
+
return this._audioTracksToPlayAtom;
|
|
97
115
|
}
|
|
98
116
|
|
|
99
|
-
/**
|
|
100
|
-
get
|
|
101
|
-
return this.
|
|
117
|
+
/** Returns the full state atom for reactive subscriptions. */
|
|
118
|
+
get stateAtom(): Atom.Atom<GlobalState> {
|
|
119
|
+
return this._stateAtom;
|
|
102
120
|
}
|
|
103
121
|
|
|
104
|
-
/**
|
|
105
|
-
|
|
106
|
-
return
|
|
122
|
+
/** Returns a derived atom for a video stream by name. */
|
|
123
|
+
videoStreamAtom(name: EncodedTrackName): Atom.Atom<MediaStream | undefined> {
|
|
124
|
+
return this._videoStreamAtomFamily(name);
|
|
107
125
|
}
|
|
108
126
|
|
|
109
|
-
/**
|
|
110
|
-
|
|
111
|
-
return this.
|
|
127
|
+
/** Returns a derived atom for an activity by key. */
|
|
128
|
+
activityAtom(key: string): Atom.Atom<ActivityState | undefined> {
|
|
129
|
+
return this._activityAtomFamily(key);
|
|
112
130
|
}
|
|
113
131
|
|
|
114
132
|
setRoomId(roomId: string): void {
|
|
@@ -152,7 +170,10 @@ export class CallManager extends Resource {
|
|
|
152
170
|
}
|
|
153
171
|
|
|
154
172
|
// TODO(burdon): Can this be mocked?
|
|
155
|
-
constructor(
|
|
173
|
+
constructor(
|
|
174
|
+
private readonly _client: Client,
|
|
175
|
+
private readonly _registry: Registry.Registry,
|
|
176
|
+
) {
|
|
156
177
|
super();
|
|
157
178
|
this._client.config.getOrThrow('runtime.services.edge.url');
|
|
158
179
|
const networkService = this._client.services.services.NetworkService;
|
|
@@ -205,12 +226,13 @@ export class CallManager extends Resource {
|
|
|
205
226
|
this._swarmSynchronizer.setJoined(false);
|
|
206
227
|
await this._swarmSynchronizer.leave();
|
|
207
228
|
await this._mediaManager.leave();
|
|
208
|
-
|
|
229
|
+
const roomId = this._registry.get(this._roomIdAtom);
|
|
230
|
+
roomId && this.left.emit(roomId);
|
|
209
231
|
}
|
|
210
232
|
|
|
211
233
|
private _onCallStateUpdated(state: CallState): void {
|
|
212
234
|
const tracksToPull = state.users
|
|
213
|
-
?.filter((user) => user.joined && user.id !== state.self
|
|
235
|
+
?.filter((user) => user.joined && user.id !== state.self!.id)
|
|
214
236
|
?.flatMap((user) => [user.tracks?.video, user.tracks?.audio, user.tracks?.screenshare])
|
|
215
237
|
.filter(isNonNullable);
|
|
216
238
|
this._mediaManager._schedulePullTracks(tracksToPull as EncodedTrackName[]);
|
|
@@ -240,7 +262,9 @@ export class CallManager extends Resource {
|
|
|
240
262
|
* Only this method is allowed to change state.
|
|
241
263
|
*/
|
|
242
264
|
private _updateState(): void {
|
|
243
|
-
this.
|
|
244
|
-
|
|
265
|
+
this._registry.set(this._stateAtom, {
|
|
266
|
+
call: this._swarmSynchronizer._getState(),
|
|
267
|
+
media: this._mediaManager._getState(),
|
|
268
|
+
});
|
|
245
269
|
}
|
|
246
270
|
}
|
|
@@ -50,7 +50,7 @@ export type CallState = {
|
|
|
50
50
|
tracks?: UserState['tracks'];
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
-
export type
|
|
53
|
+
export type CallSwarmSynchronizerProps = { networkService: NetworkService };
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Period for peer to reconnect to the call swarm gracefully if connection was lost abruptly.
|
|
@@ -76,7 +76,7 @@ export class CallSwarmSynchronizer extends Resource {
|
|
|
76
76
|
|
|
77
77
|
private _sendStateTask?: DeferredTask = undefined;
|
|
78
78
|
|
|
79
|
-
constructor({ networkService }:
|
|
79
|
+
constructor({ networkService }: CallSwarmSynchronizerProps) {
|
|
80
80
|
super();
|
|
81
81
|
this._networkService = networkService;
|
|
82
82
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { DeferredTask, Event, sleep, synchronized } from '@dxos/async';
|
|
6
6
|
import { type Context, Resource, cancelWithContext } from '@dxos/context';
|
|
7
|
+
import { invariant } from '@dxos/invariant';
|
|
7
8
|
import { log } from '@dxos/log';
|
|
8
9
|
|
|
9
10
|
import { SpeakingMonitor } from './speaking-monitor';
|
|
@@ -48,19 +49,23 @@ const VIDEO_WIDTH = 1280;
|
|
|
48
49
|
const VIDEO_HEIGHT = 720;
|
|
49
50
|
const MAX_WEB_CAM_FRAMERATE = 24;
|
|
50
51
|
const MAX_WEB_CAM_BITRATE = 120_0000;
|
|
51
|
-
const RETRY_INTERVAL =
|
|
52
|
+
const RETRY_INTERVAL = 100;
|
|
52
53
|
|
|
53
|
-
export type
|
|
54
|
+
export type MediaManagerProps = {
|
|
54
55
|
serviceConfig: CallsServiceConfig;
|
|
55
56
|
};
|
|
56
57
|
|
|
57
|
-
const USE_INAUDIBLE_AUDIO =
|
|
58
|
+
const USE_INAUDIBLE_AUDIO = true;
|
|
58
59
|
|
|
59
60
|
export class MediaManager extends Resource {
|
|
60
61
|
public readonly stateUpdated = new Event<MediaState>();
|
|
61
|
-
private readonly _state: MediaState = { pulledVideoStreams: {}, pulledAudioTracks: {} };
|
|
62
|
-
private _speakingMonitor?: SpeakingMonitor = undefined;
|
|
63
62
|
|
|
63
|
+
private readonly _state: MediaState = {
|
|
64
|
+
pulledVideoStreams: {},
|
|
65
|
+
pulledAudioTracks: {},
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
private _speakingMonitor?: SpeakingMonitor = undefined;
|
|
64
69
|
private _trackToReconcile: EncodedTrackName[] = [];
|
|
65
70
|
private _blackCanvasStreamTrack?: MediaStreamTrack = undefined;
|
|
66
71
|
private _inaudibleAudioStreamTrack?: MediaStreamTrack = undefined;
|
|
@@ -84,6 +89,7 @@ export class MediaManager extends Resource {
|
|
|
84
89
|
width: VIDEO_WIDTH,
|
|
85
90
|
height: VIDEO_HEIGHT,
|
|
86
91
|
});
|
|
92
|
+
|
|
87
93
|
this._state.videoTrack = this._blackCanvasStreamTrack;
|
|
88
94
|
this._state.videoStream = new MediaStream();
|
|
89
95
|
this._state.videoStream.addTrack(this._state.videoTrack);
|
|
@@ -136,6 +142,7 @@ export class MediaManager extends Resource {
|
|
|
136
142
|
this._state.videoStream!.removeTrack(this._state.videoTrack!);
|
|
137
143
|
this._state.videoTrack = await getUserMediaTrack('videoinput', { width: VIDEO_WIDTH, height: VIDEO_HEIGHT });
|
|
138
144
|
this._state.videoStream!.addTrack(this._state.videoTrack);
|
|
145
|
+
|
|
139
146
|
this._state.videoEnabled = true;
|
|
140
147
|
this.stateUpdated.emit(this._state);
|
|
141
148
|
this._pushTracksTask!.schedule();
|
|
@@ -225,7 +232,6 @@ export class MediaManager extends Resource {
|
|
|
225
232
|
// Wait for cloudflare to process the track.
|
|
226
233
|
await cancelWithContext(this._ctx, sleep(800));
|
|
227
234
|
const trackNames = this._trackToReconcile;
|
|
228
|
-
|
|
229
235
|
const tracksToPull = trackNames.filter(
|
|
230
236
|
(name) => !this._state.pulledAudioTracks[name] && !this._state.pulledVideoStreams[name],
|
|
231
237
|
);
|
|
@@ -248,7 +254,7 @@ export class MediaManager extends Resource {
|
|
|
248
254
|
});
|
|
249
255
|
|
|
250
256
|
// Pull new tracks.
|
|
251
|
-
await Promise.all(tracksToPull.map((name) => this._pullTrack(name)));
|
|
257
|
+
const pullResults = await Promise.all(tracksToPull.map((name) => this._pullTrack(name)));
|
|
252
258
|
|
|
253
259
|
// Close old tracks.
|
|
254
260
|
await Promise.all([...audioTracksToClose, ...videoStreamsToClose].map(([_, { ctx }]) => ctx.dispose()));
|
|
@@ -257,7 +263,14 @@ export class MediaManager extends Resource {
|
|
|
257
263
|
currentAudioTracks: Object.keys(this._state.pulledAudioTracks),
|
|
258
264
|
currentVideoStreams: Object.keys(this._state.pulledVideoStreams),
|
|
259
265
|
});
|
|
266
|
+
|
|
260
267
|
this.stateUpdated.emit(this._state);
|
|
268
|
+
if (pullResults.some(({ shouldRetry }) => shouldRetry)) {
|
|
269
|
+
await cancelWithContext(this._ctx, sleep(RETRY_INTERVAL));
|
|
270
|
+
log.info('retrying pull tracks', { tracksToPull });
|
|
271
|
+
invariant(this._pullTracksTask);
|
|
272
|
+
this._pullTracksTask.schedule();
|
|
273
|
+
}
|
|
261
274
|
}
|
|
262
275
|
|
|
263
276
|
private async _pushTracks(): Promise<void> {
|
|
@@ -266,38 +279,46 @@ export class MediaManager extends Resource {
|
|
|
266
279
|
}
|
|
267
280
|
|
|
268
281
|
let updated = false;
|
|
269
|
-
const [
|
|
270
|
-
this.
|
|
282
|
+
const [pushVideoResult, pushAudioResult, pushScreenshareResult] = await Promise.all([
|
|
283
|
+
this._maybePushTrack(this._state.videoTrack, this._state.pushedVideoTrack, [
|
|
271
284
|
{ maxFramerate: MAX_WEB_CAM_FRAMERATE, maxBitrate: MAX_WEB_CAM_BITRATE },
|
|
272
285
|
]),
|
|
273
|
-
this.
|
|
274
|
-
this.
|
|
286
|
+
this._maybePushTrack(this._state.audioTrack, this._state.pushedAudioTrack, [{ networkPriority: 'high' }]),
|
|
287
|
+
this._maybePushTrack(this._state.screenshareTrack, this._state.pushedScreenshareTrack),
|
|
275
288
|
]);
|
|
276
289
|
|
|
277
|
-
if (
|
|
278
|
-
this._state.pushedVideoTrack =
|
|
290
|
+
if (pushVideoResult.track !== this._state.pushedVideoTrack) {
|
|
291
|
+
this._state.pushedVideoTrack = pushVideoResult.track;
|
|
279
292
|
updated = true;
|
|
280
293
|
}
|
|
281
|
-
if (
|
|
282
|
-
this._state.pushedAudioTrack =
|
|
294
|
+
if (pushAudioResult.track !== this._state.pushedAudioTrack) {
|
|
295
|
+
this._state.pushedAudioTrack = pushAudioResult.track;
|
|
283
296
|
updated = true;
|
|
284
297
|
}
|
|
285
|
-
if (
|
|
286
|
-
this._state.pushedScreenshareTrack =
|
|
298
|
+
if (pushScreenshareResult.track !== this._state.pushedScreenshareTrack) {
|
|
299
|
+
this._state.pushedScreenshareTrack = pushScreenshareResult.track;
|
|
287
300
|
updated = true;
|
|
288
301
|
}
|
|
289
|
-
|
|
290
|
-
|
|
302
|
+
|
|
303
|
+
const shouldRetry = pushVideoResult.shouldRetry || pushAudioResult.shouldRetry || pushScreenshareResult.shouldRetry;
|
|
304
|
+
if (updated) {
|
|
305
|
+
this.stateUpdated.emit(this._state);
|
|
291
306
|
}
|
|
292
307
|
|
|
293
|
-
|
|
308
|
+
if (shouldRetry) {
|
|
309
|
+
await cancelWithContext(this._ctx, sleep(RETRY_INTERVAL));
|
|
310
|
+
log.info('retrying push tracks', { pushVideoResult, pushAudioResult, pushScreenshareResult });
|
|
311
|
+
invariant(this._pushTracksTask);
|
|
312
|
+
this._pushTracksTask.schedule();
|
|
313
|
+
}
|
|
294
314
|
}
|
|
295
315
|
|
|
296
|
-
private async _pullTrack(name: EncodedTrackName): Promise<
|
|
316
|
+
private async _pullTrack(name: EncodedTrackName): Promise<{ shouldRetry: boolean }> {
|
|
297
317
|
const ctx = this._ctx.derive();
|
|
298
318
|
try {
|
|
299
319
|
const trackData = TrackNameCodec.decode(name);
|
|
300
|
-
|
|
320
|
+
// We need to set mid here to `undefined`, because mid is peer specific.
|
|
321
|
+
const track = await this._state.peer!.pullTrack({ trackData: { ...trackData, mid: undefined }, ctx });
|
|
301
322
|
if (track?.readyState === 'ended') {
|
|
302
323
|
throw new Error('Pulled track ended immediately');
|
|
303
324
|
}
|
|
@@ -306,7 +327,7 @@ export class MediaManager extends Resource {
|
|
|
306
327
|
case 'audio': {
|
|
307
328
|
this._state.pulledAudioTracks[name] = { track, ctx };
|
|
308
329
|
ctx.onDispose(() => delete this._state.pulledAudioTracks[name]);
|
|
309
|
-
|
|
330
|
+
return { shouldRetry: false };
|
|
310
331
|
}
|
|
311
332
|
case 'video': {
|
|
312
333
|
const mediaStream = new MediaStream();
|
|
@@ -317,33 +338,41 @@ export class MediaManager extends Resource {
|
|
|
317
338
|
track.stop();
|
|
318
339
|
delete this._state.pulledVideoStreams[name];
|
|
319
340
|
});
|
|
320
|
-
|
|
341
|
+
return { shouldRetry: false };
|
|
321
342
|
}
|
|
322
343
|
default:
|
|
323
344
|
throw new Error(`Invalid track kind: ${track?.kind}`);
|
|
324
345
|
}
|
|
325
346
|
} catch (err) {
|
|
326
|
-
log.
|
|
347
|
+
log.info('failed to pull track', { err, name });
|
|
327
348
|
void ctx.dispose();
|
|
328
|
-
|
|
329
|
-
log.verbose('retrying pull track', { name });
|
|
330
|
-
this._pullTracksTask!.schedule();
|
|
349
|
+
return { shouldRetry: true };
|
|
331
350
|
}
|
|
332
351
|
}
|
|
333
352
|
|
|
334
|
-
private async
|
|
353
|
+
private async _maybePushTrack(
|
|
335
354
|
track?: MediaStreamTrack,
|
|
336
355
|
previousTrack?: TrackObject,
|
|
337
356
|
encodings?: RTCRtpEncodingParameters[],
|
|
338
|
-
): Promise<TrackObject
|
|
357
|
+
): Promise<{ track?: TrackObject; shouldRetry?: boolean }> {
|
|
339
358
|
if (!track && !previousTrack) {
|
|
340
|
-
return;
|
|
359
|
+
return { track: undefined };
|
|
341
360
|
}
|
|
342
361
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
362
|
+
const ctx = this._ctx.derive();
|
|
363
|
+
try {
|
|
364
|
+
return {
|
|
365
|
+
track: await this._state.peer!.pushTrack({
|
|
366
|
+
ctx,
|
|
367
|
+
track: track ?? null,
|
|
368
|
+
previousTrack,
|
|
369
|
+
encodings,
|
|
370
|
+
}),
|
|
371
|
+
};
|
|
372
|
+
} catch (err) {
|
|
373
|
+
log.info('failed to push track', { err, track, previousTrack, encodings });
|
|
374
|
+
void ctx.dispose();
|
|
375
|
+
return { shouldRetry: true };
|
|
376
|
+
}
|
|
348
377
|
}
|
|
349
378
|
}
|
package/src/calls/types.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { invariant } from '@dxos/invariant';
|
|
5
6
|
import { buf } from '@dxos/protocols/buf';
|
|
6
7
|
import {
|
|
7
8
|
type ActivitySchema,
|
|
@@ -61,10 +62,13 @@ export type EncodedTrackName = string & { __brand: 'EncodedTrackName' };
|
|
|
61
62
|
|
|
62
63
|
export const TrackNameCodec = {
|
|
63
64
|
encode: (trackData: TrackObject): EncodedTrackName => {
|
|
64
|
-
|
|
65
|
+
invariant(trackData.sessionId);
|
|
66
|
+
invariant(trackData.trackName);
|
|
67
|
+
invariant(trackData.mid);
|
|
68
|
+
return (trackData.sessionId + '/' + trackData.trackName + '/' + trackData.mid) as EncodedTrackName;
|
|
65
69
|
},
|
|
66
70
|
decode: (name: EncodedTrackName): TrackObject => {
|
|
67
|
-
const [sessionId, trackName] = name.split('/');
|
|
68
|
-
return { sessionId, trackName, location: 'remote' };
|
|
71
|
+
const [sessionId, trackName, mid] = name.split('/');
|
|
72
|
+
return { sessionId, trackName, location: 'remote', mid };
|
|
69
73
|
},
|
|
70
74
|
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { PersistentLifecycle } from '@dxos/async';
|
|
5
|
+
import { PersistentLifecycle, Trigger, scheduleTask } from '@dxos/async';
|
|
6
6
|
import { type Context, Resource } from '@dxos/context';
|
|
7
7
|
import { invariant } from '@dxos/invariant';
|
|
8
8
|
import { log } from '@dxos/log';
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
type TrackObject,
|
|
15
15
|
type TracksResponse,
|
|
16
16
|
} from '../types';
|
|
17
|
-
|
|
18
17
|
import { HistoryCache } from './history-cache';
|
|
19
18
|
import { BulkRequestDispatcher, FIFOScheduler } from './task-scheduling';
|
|
20
19
|
|
|
@@ -27,18 +26,20 @@ export type Session = {
|
|
|
27
26
|
|
|
28
27
|
export type CallsServiceConfig = {
|
|
29
28
|
apiBase: string;
|
|
30
|
-
|
|
29
|
+
apiExtraProps?: string;
|
|
31
30
|
iceServers?: RTCIceServer[];
|
|
32
31
|
};
|
|
33
32
|
|
|
34
33
|
export type HistoryRecord =
|
|
35
34
|
| {
|
|
35
|
+
endpoint: string;
|
|
36
36
|
type: 'request';
|
|
37
37
|
time: string;
|
|
38
38
|
method: string;
|
|
39
39
|
body: any;
|
|
40
40
|
}
|
|
41
41
|
| {
|
|
42
|
+
endpoint: string;
|
|
42
43
|
type: 'response';
|
|
43
44
|
time: string;
|
|
44
45
|
status: number;
|
|
@@ -116,7 +117,7 @@ export class CallsServicePeer extends Resource {
|
|
|
116
117
|
});
|
|
117
118
|
peerConnection.addEventListener('connectionstatechange', () => {
|
|
118
119
|
if (peerConnection.connectionState === 'failed' || peerConnection.connectionState === 'closed') {
|
|
119
|
-
log.
|
|
120
|
+
log.info('calls connection failed', { state: peerConnection.connectionState });
|
|
120
121
|
void this._persistentLifecycle.scheduleRestart();
|
|
121
122
|
}
|
|
122
123
|
});
|
|
@@ -125,7 +126,7 @@ export class CallsServicePeer extends Resource {
|
|
|
125
126
|
peerConnection.addEventListener('iceconnectionstatechange', () => {
|
|
126
127
|
clearTimeout(iceTimeout);
|
|
127
128
|
if (peerConnection.iceConnectionState === 'failed' || peerConnection.iceConnectionState === 'closed') {
|
|
128
|
-
log.
|
|
129
|
+
log.info('calls connection to ICEs failed', { state: peerConnection.iceConnectionState });
|
|
129
130
|
void this._persistentLifecycle.scheduleRestart();
|
|
130
131
|
} else if (peerConnection.iceConnectionState === 'disconnected') {
|
|
131
132
|
// TODO(mykola): we should start to inspect the connection stats from here on for
|
|
@@ -138,7 +139,7 @@ export class CallsServicePeer extends Resource {
|
|
|
138
139
|
return;
|
|
139
140
|
}
|
|
140
141
|
|
|
141
|
-
log.
|
|
142
|
+
log.info('calls iceConnectionState timed out', { state: peerConnection.iceConnectionState, timeoutSeconds });
|
|
142
143
|
void this._persistentLifecycle.scheduleRestart();
|
|
143
144
|
}, timeoutSeconds * 1_000);
|
|
144
145
|
}
|
|
@@ -155,6 +156,7 @@ export class CallsServicePeer extends Resource {
|
|
|
155
156
|
|
|
156
157
|
private async _fetch<T extends ErrorResponse>(relativePath: string, requestInit?: RequestInit): Promise<T> {
|
|
157
158
|
this.history.push({
|
|
159
|
+
endpoint: relativePath,
|
|
158
160
|
type: 'request',
|
|
159
161
|
time: new Date().toISOString(),
|
|
160
162
|
method: requestInit?.method ?? 'GET',
|
|
@@ -170,6 +172,7 @@ export class CallsServicePeer extends Resource {
|
|
|
170
172
|
try {
|
|
171
173
|
const data = (await response.clone().json()) as T;
|
|
172
174
|
this.history.push({
|
|
175
|
+
endpoint: relativePath,
|
|
173
176
|
type: 'response',
|
|
174
177
|
time: new Date().toISOString(),
|
|
175
178
|
status: response.status,
|
|
@@ -183,6 +186,7 @@ export class CallsServicePeer extends Resource {
|
|
|
183
186
|
} catch (error) {
|
|
184
187
|
const text = await response.text();
|
|
185
188
|
this.history.push({
|
|
189
|
+
endpoint: relativePath,
|
|
186
190
|
type: 'response',
|
|
187
191
|
time: new Date().toISOString(),
|
|
188
192
|
status: response.status,
|
|
@@ -204,11 +208,11 @@ export class CallsServicePeer extends Resource {
|
|
|
204
208
|
sessionId,
|
|
205
209
|
trackName,
|
|
206
210
|
}: {
|
|
211
|
+
ctx: Context;
|
|
207
212
|
peerConnection: RTCPeerConnection;
|
|
208
213
|
transceiver: RTCRtpTransceiver;
|
|
209
214
|
sessionId: string;
|
|
210
215
|
trackName: string;
|
|
211
|
-
ctx?: Context;
|
|
212
216
|
}): Promise<TrackObject | void> {
|
|
213
217
|
log.verbose('pushing track ', trackName);
|
|
214
218
|
const pushedTrackPromise = this.pushTrackDispatcher
|
|
@@ -246,9 +250,13 @@ export class CallsServicePeer extends Resource {
|
|
|
246
250
|
};
|
|
247
251
|
}),
|
|
248
252
|
)
|
|
249
|
-
.then(({ tracks }) => {
|
|
253
|
+
.then(async ({ tracks }) => {
|
|
250
254
|
const trackData = tracks.find((t) => t.mid === transceiver.mid);
|
|
251
255
|
if (trackData) {
|
|
256
|
+
// we wait for the transceiver to start sending data before we emit
|
|
257
|
+
// the track metadata to ensure that the track will be able to be
|
|
258
|
+
// pulled before making the metadata available to anyone else.
|
|
259
|
+
// await waitForTransceiverToSendData(ctx, transceiver);
|
|
252
260
|
return {
|
|
253
261
|
...trackData,
|
|
254
262
|
sessionId,
|
|
@@ -257,9 +265,6 @@ export class CallsServicePeer extends Resource {
|
|
|
257
265
|
} else {
|
|
258
266
|
log.error('missing track data');
|
|
259
267
|
}
|
|
260
|
-
})
|
|
261
|
-
.catch((err) => {
|
|
262
|
-
log.catch(err);
|
|
263
268
|
});
|
|
264
269
|
|
|
265
270
|
const onDispose = async () => {
|
|
@@ -281,8 +286,8 @@ export class CallsServicePeer extends Resource {
|
|
|
281
286
|
previousTrack,
|
|
282
287
|
}: {
|
|
283
288
|
track: MediaStreamTrack | null;
|
|
289
|
+
ctx: Context;
|
|
284
290
|
encodings?: RTCRtpEncodingParameters[];
|
|
285
|
-
ctx?: Context;
|
|
286
291
|
previousTrack?: TrackObject;
|
|
287
292
|
}): Promise<TrackObject | undefined> {
|
|
288
293
|
await this.waitUntilOpen();
|
|
@@ -405,7 +410,7 @@ export class CallsServicePeer extends Resource {
|
|
|
405
410
|
})
|
|
406
411
|
.catch((err) => log.catch(err));
|
|
407
412
|
} else {
|
|
408
|
-
log.
|
|
413
|
+
log.info('missing track info', { trackData, availableTracks: Array.from(trackMap.keys()) });
|
|
409
414
|
}
|
|
410
415
|
});
|
|
411
416
|
|
|
@@ -529,3 +534,47 @@ const peerConnectionIsConnected = async (peerConnection: RTCPeerConnection) => {
|
|
|
529
534
|
await connected;
|
|
530
535
|
}
|
|
531
536
|
};
|
|
537
|
+
|
|
538
|
+
const INITIAL_DELAY = 50;
|
|
539
|
+
const MAX_DELAY = 500;
|
|
540
|
+
const MAX_RETRIES = 20;
|
|
541
|
+
const WAIT_FOR_DATA_TIMEOUT = 10_000;
|
|
542
|
+
|
|
543
|
+
const waitForTransceiverToSendData = async (ctx: Context, transceiver: RTCRtpTransceiver): Promise<void> => {
|
|
544
|
+
let delay = INITIAL_DELAY;
|
|
545
|
+
let checks = 0;
|
|
546
|
+
const waitForData = new Trigger();
|
|
547
|
+
ctx.onDispose(() => waitForData.throw(new Error('Transceiver was closed')));
|
|
548
|
+
|
|
549
|
+
const checkStats = async () => {
|
|
550
|
+
if (ctx.disposed) return;
|
|
551
|
+
|
|
552
|
+
try {
|
|
553
|
+
const stats = await transceiver.sender.getStats();
|
|
554
|
+
let dataFound = false;
|
|
555
|
+
stats.forEach((stat) => {
|
|
556
|
+
if (stat.type === 'outbound-rtp' && stat.bytesSent > 0) {
|
|
557
|
+
dataFound = true;
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
if (dataFound) {
|
|
562
|
+
waitForData.wake();
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
} catch {
|
|
566
|
+
// Stats might not be available yet, continue checking
|
|
567
|
+
}
|
|
568
|
+
checks++;
|
|
569
|
+
if (checks > MAX_RETRIES) {
|
|
570
|
+
waitForData.throw(new Error('Transceiver did not send data'));
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
delay = Math.min(delay * 2, MAX_DELAY); // Exponential backoff with max cap
|
|
575
|
+
scheduleTask(ctx, checkStats, delay);
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
void checkStats();
|
|
579
|
+
return waitForData.wait({ timeout: WAIT_FOR_DATA_TIMEOUT });
|
|
580
|
+
};
|