@dxos/plugin-thread 0.12.0-next-73daef452f1464b62efdbca75fb0067c1066f264 → 0.13.0
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/PLUGIN.mdl +122 -1
- package/dist/lib/ChannelBackend.mjs +46 -3
- package/dist/lib/ChannelBackend.mjs.map +1 -1
- package/dist/lib/ThreadCapabilities.mjs.map +1 -1
- package/dist/lib/ThreadOperation.mjs +101 -4
- package/dist/lib/ThreadOperation.mjs.map +1 -1
- package/dist/lib/ThreadOperationHandlerSet.mjs +19 -0
- package/dist/lib/ThreadOperationHandlerSet.mjs.map +1 -0
- package/dist/lib/capabilities.browser.mjs +36 -0
- package/dist/lib/capabilities.browser.mjs.map +1 -0
- package/dist/lib/capabilities.mjs +8 -5
- package/dist/lib/capabilities.mjs.map +1 -1
- package/dist/lib/capabilities.node.mjs +6 -1
- package/dist/lib/capabilities.node.mjs.map +1 -1
- package/dist/lib/capabilities.tauri.mjs +36 -0
- package/dist/lib/capabilities.tauri.mjs.map +1 -0
- package/dist/lib/capabilities.workerd.mjs +6 -1
- package/dist/lib/capabilities.workerd.mjs.map +1 -1
- package/dist/lib/chunk-ChannelArticle.mjs +16 -19
- package/dist/lib/chunk-ChannelArticle.mjs.map +1 -1
- package/dist/lib/chunk-ChannelCreatePanel.mjs +5 -4
- package/dist/lib/chunk-ChannelCreatePanel.mjs.map +1 -1
- package/dist/lib/chunk-PLUGIN.mjs +6 -0
- package/dist/lib/chunk-PLUGIN.mjs.map +1 -0
- package/dist/lib/chunk-ThreadArticle.mjs +13 -8
- package/dist/lib/chunk-ThreadArticle.mjs.map +1 -1
- package/dist/lib/chunk-app-graph-builder.mjs +7 -4
- package/dist/lib/chunk-app-graph-builder.mjs.map +1 -1
- package/dist/lib/chunk-append-channel-message.mjs +3 -14
- package/dist/lib/chunk-append-channel-message.mjs.map +1 -1
- package/dist/lib/chunk-channel-backend-feed.mjs +8 -18
- package/dist/lib/chunk-channel-backend-feed.mjs.map +1 -1
- package/dist/lib/chunk-connect-channel.mjs +14 -0
- package/dist/lib/chunk-connect-channel.mjs.map +1 -0
- package/dist/lib/chunk-create-channel.mjs +1 -1
- package/dist/lib/chunk-create-object.mjs +1 -1
- package/dist/lib/chunk-disconnect-channel.mjs +14 -0
- package/dist/lib/chunk-disconnect-channel.mjs.map +1 -0
- package/dist/lib/chunk-get-channel-status.mjs +14 -0
- package/dist/lib/chunk-get-channel-status.mjs.map +1 -0
- package/dist/lib/chunk-open-direct.mjs +15 -0
- package/dist/lib/chunk-open-direct.mjs.map +1 -0
- package/dist/lib/chunk-operation-handler.mjs +2 -2
- package/dist/lib/chunk-operation-handler.mjs.map +1 -1
- package/dist/lib/chunk-react-surface.mjs +2 -2
- package/dist/lib/chunk-react-surface.mjs.map +1 -1
- package/dist/lib/chunk-send-to-channel.mjs +28 -0
- package/dist/lib/chunk-send-to-channel.mjs.map +1 -0
- package/dist/lib/components.mjs +9 -7
- package/dist/lib/components.mjs.map +1 -1
- package/dist/lib/containers.mjs.map +1 -1
- package/dist/lib/hooks.mjs +4 -3
- package/dist/lib/hooks.mjs.map +1 -1
- package/dist/lib/index.mjs +2 -4
- package/dist/lib/meta.mjs +1 -0
- package/dist/lib/meta.mjs.map +1 -1
- package/dist/lib/operations.mjs +2 -9
- package/dist/lib/translations.mjs +1 -1
- package/dist/lib/translations.mjs.map +1 -1
- package/dist/types/src/capabilities/channel-backend-feed.d.ts.map +1 -1
- package/dist/types/src/capabilities/gen/browser.d.ts +10 -0
- package/dist/types/src/capabilities/gen/browser.d.ts.map +1 -0
- package/dist/types/src/capabilities/gen/node.d.ts.map +1 -1
- package/dist/types/src/capabilities/gen/tauri.d.ts +10 -0
- package/dist/types/src/capabilities/gen/tauri.d.ts.map +1 -0
- package/dist/types/src/capabilities/gen/workerd.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/components/MessageThread/MessageThread.d.ts +2 -2
- package/dist/types/src/components/MessageThread/MessageThread.d.ts.map +1 -1
- package/dist/types/src/components/MessageThread/index.d.ts +1 -1
- package/dist/types/src/components/MessageThread/index.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/containers/ChannelArticle/ChannelArticle.d.ts +1 -1
- package/dist/types/src/containers/ChannelArticle/ChannelArticle.d.ts.map +1 -1
- package/dist/types/src/containers/ChannelArticle/ChannelArticle.stories.d.ts +1 -1
- package/dist/types/src/containers/ChannelArticle/ChannelArticle.stories.d.ts.map +1 -1
- package/dist/types/src/containers/ChannelArticle/index.d.ts +1 -1
- package/dist/types/src/containers/ChannelArticle/index.d.ts.map +1 -1
- package/dist/types/src/containers/ChannelCreatePanel/ChannelCreatePanel.d.ts +1 -1
- package/dist/types/src/containers/ChannelCreatePanel/ChannelCreatePanel.d.ts.map +1 -1
- package/dist/types/src/containers/ChannelCreatePanel/index.d.ts +1 -1
- package/dist/types/src/containers/ChannelCreatePanel/index.d.ts.map +1 -1
- package/dist/types/src/containers/ThreadArticle/ThreadArticle.d.ts +2 -2
- package/dist/types/src/containers/ThreadArticle/ThreadArticle.d.ts.map +1 -1
- package/dist/types/src/containers/ThreadArticle/index.d.ts +1 -1
- package/dist/types/src/containers/ThreadArticle/index.d.ts.map +1 -1
- package/dist/types/src/containers/index.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -2
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useStatus.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -4
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/operations/ThreadOperationHandlerSet.d.ts +3 -0
- package/dist/types/src/operations/ThreadOperationHandlerSet.d.ts.map +1 -0
- package/dist/types/src/operations/append-channel-message.d.ts.map +1 -1
- package/dist/types/src/operations/channel-operations.test.d.ts +2 -0
- package/dist/types/src/operations/channel-operations.test.d.ts.map +1 -0
- package/dist/types/src/operations/connect-channel.d.ts +5 -0
- package/dist/types/src/operations/connect-channel.d.ts.map +1 -0
- package/dist/types/src/operations/disconnect-channel.d.ts +5 -0
- package/dist/types/src/operations/disconnect-channel.d.ts.map +1 -0
- package/dist/types/src/operations/get-channel-status.d.ts +5 -0
- package/dist/types/src/operations/get-channel-status.d.ts.map +1 -0
- package/dist/types/src/operations/index.d.ts +1 -2
- package/dist/types/src/operations/index.d.ts.map +1 -1
- package/dist/types/src/operations/open-direct.d.ts +5 -0
- package/dist/types/src/operations/open-direct.d.ts.map +1 -0
- package/dist/types/src/operations/send-to-channel.d.ts +5 -0
- package/dist/types/src/operations/send-to-channel.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/ChannelBackend.d.ts +79 -1
- package/dist/types/src/types/ChannelBackend.d.ts.map +1 -1
- package/dist/types/src/types/ThreadCapabilities.d.ts +30 -4
- package/dist/types/src/types/ThreadCapabilities.d.ts.map +1 -1
- package/dist/types/src/types/ThreadOperation.d.ts +78 -2
- package/dist/types/src/types/ThreadOperation.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +4 -4
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dx.config.ts +3 -0
- package/package.json +53 -40
- package/src/capabilities/app-graph-builder.ts +3 -2
- package/src/capabilities/channel-backend-feed.ts +5 -10
- package/src/capabilities/gen/browser.ts +57 -0
- package/src/capabilities/gen/node.ts +5 -5
- package/src/capabilities/gen/tauri.ts +57 -0
- package/src/capabilities/gen/workerd.ts +5 -5
- package/src/capabilities/index.ts +8 -8
- package/src/capabilities/operation-handler.ts +1 -1
- package/src/capabilities/react-surface.ts +2 -2
- package/src/components/MessageThread/MessageThread.tsx +11 -14
- package/src/components/MessageThread/index.ts +1 -1
- package/src/components/index.ts +1 -1
- package/src/containers/ChannelArticle/ChannelArticle.stories.tsx +4 -4
- package/src/containers/ChannelArticle/ChannelArticle.tsx +17 -20
- package/src/containers/ChannelArticle/index.ts +1 -1
- package/src/containers/ChannelCreatePanel/ChannelCreatePanel.tsx +10 -5
- package/src/containers/ChannelCreatePanel/index.ts +1 -1
- package/src/containers/ThreadArticle/ThreadArticle.stories.tsx +7 -7
- package/src/containers/ThreadArticle/ThreadArticle.tsx +21 -12
- package/src/containers/ThreadArticle/index.ts +1 -1
- package/src/containers/index.ts +3 -3
- package/src/hooks/index.ts +2 -2
- package/src/hooks/useMessages.ts +2 -2
- package/src/hooks/useStatus.ts +4 -1
- package/src/index.ts +2 -4
- package/src/meta.ts +1 -1
- package/src/operations/ThreadOperationHandlerSet.ts +20 -0
- package/src/operations/append-channel-message.ts +2 -6
- package/src/operations/channel-operations.test.ts +185 -0
- package/src/operations/connect-channel.ts +23 -0
- package/src/operations/disconnect-channel.ts +23 -0
- package/src/operations/get-channel-status.ts +23 -0
- package/src/operations/index.ts +1 -9
- package/src/operations/open-direct.ts +32 -0
- package/src/operations/send-to-channel.ts +33 -0
- package/src/plugin.test.ts +3 -3
- package/src/translations.ts +2 -2
- package/src/types/ChannelBackend.test.ts +2 -2
- package/src/types/ChannelBackend.ts +66 -2
- package/src/types/ThreadCapabilities.ts +41 -4
- package/src/types/ThreadOperation.ts +114 -5
- package/src/types/index.ts +4 -4
- package/dist/lib/chunk-paths.mjs +0 -8
- package/dist/lib/chunk-paths.mjs.map +0 -1
- package/dist/lib/operations.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.workerd.mjs","names":[],"sources":["../../src/capabilities/gen/workerd.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// GENERATED by dx-plugin — do not edit. Sliced from ../index.ts for the 'workerd' condition.\n\nimport * as ActivationEvents from '@dxos/app-framework/ActivationEvents';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\nimport { translations as threadTranslations } from '@dxos/react-ui-thread/translations';\n\nimport { translations } from '#translations';\nimport { ThreadCapabilities, ThreadEvents } from '#types';\n\n// The graph builder reads the call manager OPTIONALLY (reactive atom with an absence guard),\n// so no spec-level require: a hard cross-plugin require would fail this plugin whenever\n// plugin-calls is disabled. Cross-feature requires are only valid with a plugin-level dependsOn.\nexport const AppGraphBuilder = AppCapability.appGraphBuilder(() => import('../app-graph-builder'));\n\nexport const ChannelBackendFeed = Capability.lazyModule(\n 'ChannelBackendFeed',\n {\n provides: [ThreadCapabilities.ChannelBackend],\n activatesOn: ThreadEvents.Start,\n environments: ['node', 'workerd'],\n },\n () => import('../channel-backend-feed'),\n);\n\nexport const OperationHandler = AppCapability.operationHandler(() => import('../operation-handler'), {\n activatesOn: ActivationEvents.Idle,\n});\n\nexport const Schema = AppCapability.schema(() => import('../schema'));\n\nexport const Translations = AppCapability.translations([...translations, ...threadTranslations]);\n\nexport const CreateObject = undefined;\nexport const PluginAsset = undefined;\nexport const ReactSurface = undefined;\n"],"mappings":";;;;;;;AAiBA,IAAa,kBAAkB,cAAc,sBAAsB,OAAO,
|
|
1
|
+
{"version":3,"file":"capabilities.workerd.mjs","names":[],"sources":["../../src/capabilities/gen/workerd.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// GENERATED by dx-plugin — do not edit. Sliced from ../index.ts for the 'workerd' condition.\n\nimport * as ActivationEvents from '@dxos/app-framework/ActivationEvents';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\nimport { translations as threadTranslations } from '@dxos/react-ui-thread/translations';\n\nimport { translations } from '#translations';\nimport { ThreadCapabilities, ThreadEvents } from '#types';\n\n// The graph builder reads the call manager OPTIONALLY (reactive atom with an absence guard),\n// so no spec-level require: a hard cross-plugin require would fail this plugin whenever\n// plugin-calls is disabled. Cross-feature requires are only valid with a plugin-level dependsOn.\nexport const AppGraphBuilder = AppCapability.appGraphBuilder(() => import('../app-graph-builder.ts'));\n\nexport const ChannelBackendFeed = Capability.lazyModule(\n 'ChannelBackendFeed',\n {\n provides: [ThreadCapabilities.ChannelBackend],\n activatesOn: ThreadEvents.Start,\n environments: ['browser', 'node', 'tauri', 'workerd'],\n },\n () => import('../channel-backend-feed.ts'),\n);\n\nexport const OperationHandler = AppCapability.operationHandler(() => import('../operation-handler.ts'), {\n activatesOn: ActivationEvents.Idle,\n});\n\nexport const Schema = AppCapability.schema(() => import('../schema.ts'));\n\nexport const Translations = AppCapability.translations([...translations, ...threadTranslations]);\n\nexport const CreateObject = undefined;\nexport const PluginAsset = undefined;\nexport const ReactSurface = undefined;\n"],"mappings":";;;;;;;AAiBA,IAAa,kBAAkB,cAAc,sBAAsB,OAAO,gCAA0B;AAEpG,IAAa,qBAAqB,WAAW,WAC3C,sBACA;CACE,UAAU,CAAC,mBAAmB,cAAc;CAC5C,aAAa,aAAa;CAC1B,cAAc;EAAC;EAAW;EAAQ;EAAS;CAAS;AACtD,SACM,OAAO,mCACf;AAEA,IAAa,mBAAmB,cAAc,uBAAuB,OAAO,kCAA4B,EACtG,aAAa,iBAAiB,KAChC,CAAC;AAED,IAAa,SAAS,cAAc,aAAa,OAAO,qBAAe;AAEvE,IAAa,eAAe,cAAc,aAAa,CAAC,GAAG,gBAAc,GAAG,YAAkB,CAAC;AAE/F,IAAa,eAAe,KAAA;AAC5B,IAAa,cAAc,KAAA;AAC3B,IAAa,eAAe,KAAA"}
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { ChannelBackend, ThreadCapabilities, ThreadOperation } from "#types";
|
|
2
2
|
import { meta } from "#meta";
|
|
3
|
-
import { useMessages, useStatus } from "#hooks";
|
|
4
3
|
import { useCallback } from "react";
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import { Panel } from "@dxos/react-ui";
|
|
4
|
+
import * as Surface from "@dxos/app-framework/Surface";
|
|
5
|
+
import * as AppSurface from "@dxos/app-toolkit/AppSurface";
|
|
8
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import * as Hooks from "@dxos/app-framework/Hooks";
|
|
9
8
|
import { Obj } from "@dxos/echo";
|
|
10
9
|
import * as CallsCapabilities from "@dxos/plugin-calls/CallsCapabilities";
|
|
11
10
|
import { useAtomValue } from "@effect/atom-react/Hooks";
|
|
12
|
-
import * as Atom from "effect/
|
|
11
|
+
import * as Atom from "effect/reactivity/Atom";
|
|
13
12
|
import { useIdentity, useMembers } from "@dxos/halo-react";
|
|
14
13
|
import { log } from "@dxos/log";
|
|
15
14
|
import { getSpace } from "@dxos/react-client/echo";
|
|
16
|
-
import {
|
|
15
|
+
import { ActionToolbar, MenuBuilder, useMenuBuilder } from "@dxos/react-ui-menu";
|
|
16
|
+
import * as Panel from "@dxos/react-ui/Panel";
|
|
17
17
|
import { MessageThread } from "#components";
|
|
18
|
+
import { useMessages, useStatus } from "#hooks";
|
|
18
19
|
//#region src/containers/ChannelArticle/ChannelArticle.tsx
|
|
19
20
|
var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/containers/ChannelArticle/ChannelArticle.tsx";
|
|
20
21
|
var NOT_JOINED = Atom.make(false);
|
|
@@ -33,13 +34,13 @@ var ChannelArticle = ({ role, subject: channel, attendableId, chatOnly }) => {
|
|
|
33
34
|
const members = useMembers(space?.id);
|
|
34
35
|
const id = channel ? Obj.getURI(channel) : void 0;
|
|
35
36
|
const activity = useStatus(space, id);
|
|
36
|
-
const { invokePromise } = useOperationInvoker();
|
|
37
|
-
const providers = useCapabilities(ThreadCapabilities.ChannelBackend);
|
|
37
|
+
const { invokePromise } = Hooks.useOperationInvoker();
|
|
38
|
+
const providers = Hooks.useCapabilities(ThreadCapabilities.ChannelBackend);
|
|
38
39
|
const provider = channel ? ChannelBackend.resolveProvider(providers, channel.backend.kind) : void 0;
|
|
39
40
|
const messages = useMessages(channel);
|
|
40
41
|
const readOnly = channel ? provider?.readOnly?.(channel) ?? Obj.getMeta(channel).keys.length > 0 : false;
|
|
41
|
-
const callProvider = useCapabilities(CallsCapabilities.CallTransportProvider)[0];
|
|
42
|
-
const callManager = useCapabilities(CallsCapabilities.Manager)[0];
|
|
42
|
+
const callProvider = Hooks.useCapabilities(CallsCapabilities.CallTransportProvider)[0];
|
|
43
|
+
const callManager = Hooks.useCapabilities(CallsCapabilities.Manager)[0];
|
|
43
44
|
const joined = useAtomValue(callManager?.joinedAtom ?? NOT_JOINED);
|
|
44
45
|
const currentRoomId = useAtomValue(callManager?.roomIdAtom ?? NO_ROOM);
|
|
45
46
|
const inThisCall = !!id && joined && currentRoomId === id;
|
|
@@ -53,7 +54,7 @@ var ChannelArticle = ({ role, subject: channel, attendableId, chatOnly }) => {
|
|
|
53
54
|
log.catch(err, void 0, {
|
|
54
55
|
"~LogMeta": "~LogMeta",
|
|
55
56
|
F: __dxlog_file,
|
|
56
|
-
L:
|
|
57
|
+
L: 79,
|
|
57
58
|
S: void 0
|
|
58
59
|
});
|
|
59
60
|
}
|
|
@@ -80,21 +81,17 @@ var ChannelArticle = ({ role, subject: channel, attendableId, chatOnly }) => {
|
|
|
80
81
|
if (!space || !channel || !id) return null;
|
|
81
82
|
return /* @__PURE__ */ jsxs(Panel.Root, {
|
|
82
83
|
role,
|
|
83
|
-
children: [canStartCall && /* @__PURE__ */ jsx(
|
|
84
|
+
children: [canStartCall && /* @__PURE__ */ jsx(Panel.Header, { children: /* @__PURE__ */ jsx(ActionToolbar, {
|
|
84
85
|
...menuActions,
|
|
85
|
-
attendableId
|
|
86
|
-
|
|
87
|
-
asChild: true,
|
|
88
|
-
children: /* @__PURE__ */ jsx(Menu.Toolbar, { children: /* @__PURE__ */ jsx(Menu.Items, {}) })
|
|
89
|
-
})
|
|
90
|
-
}), showCall ? /* @__PURE__ */ jsx(Panel.Content, { children: /* @__PURE__ */ jsx(Surface.Surface, {
|
|
86
|
+
attendableId
|
|
87
|
+
}) }), showCall ? /* @__PURE__ */ jsx(Panel.Body, { children: /* @__PURE__ */ jsx(Surface.Surface, {
|
|
91
88
|
type: AppSurface.Article,
|
|
92
89
|
data: {
|
|
93
90
|
subject: { roomId: id },
|
|
94
91
|
attendableId
|
|
95
92
|
},
|
|
96
93
|
limit: 1
|
|
97
|
-
}) }) : /* @__PURE__ */ jsx(Panel.
|
|
94
|
+
}) }) : /* @__PURE__ */ jsx(Panel.Body, {
|
|
98
95
|
asChild: true,
|
|
99
96
|
children: /* @__PURE__ */ jsx(MessageThread, {
|
|
100
97
|
id,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-ChannelArticle.mjs","names":[],"sources":["../../src/containers/ChannelArticle/ChannelArticle.tsx"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport { useAtomValue } from '@effect/atom-react/Hooks';\nimport * as Atom from 'effect/
|
|
1
|
+
{"version":3,"file":"chunk-ChannelArticle.mjs","names":[],"sources":["../../src/containers/ChannelArticle/ChannelArticle.tsx"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport { useAtomValue } from '@effect/atom-react/Hooks';\nimport * as Atom from 'effect/reactivity/Atom';\nimport React, { useCallback } from 'react';\n\nimport * as Hooks from '@dxos/app-framework/Hooks';\nimport * as Surface from '@dxos/app-framework/Surface';\nimport * as AppSurface from '@dxos/app-toolkit/AppSurface';\nimport { Obj } from '@dxos/echo';\nimport { useIdentity, useMembers } from '@dxos/halo-react';\nimport { log } from '@dxos/log';\nimport * as CallsCapabilities from '@dxos/plugin-calls/CallsCapabilities';\nimport { getSpace } from '@dxos/react-client/echo';\nimport { ActionToolbar, MenuBuilder, useMenuBuilder } from '@dxos/react-ui-menu';\nimport * as Panel from '@dxos/react-ui/Panel';\nimport { type Channel } from '@dxos/types';\n\nimport { MessageThread } from '#components';\nimport { useMessages, useStatus } from '#hooks';\nimport { meta } from '#meta';\nimport { ChannelBackend, ThreadCapabilities, ThreadOperation } from '#types';\n\n// Stable fallbacks so `useAtomValue` always receives an atom when plugin-calls isn't present.\nconst NOT_JOINED = Atom.make(false);\nconst NO_ROOM = Atom.make<string | undefined>(undefined);\n\nexport type ChannelArticleProps = AppSurface.ObjectArticleProps<\n Channel.Channel | undefined,\n {\n roomId?: string;\n fullscreen?: boolean;\n /** Always render the chat, even while in this channel's call (used by the in-call chat companion). */\n chatOnly?: boolean;\n }\n>;\n\n/**\n * Channel article: renders the channel chat inside a document panel. Messages\n * are read and written through the channel's backend provider (resolved by\n * `channel.backend.kind`), so the container is agnostic to where messages are\n * stored. Read-only state defaults to the provider's policy, or to \"channel\n * carries foreign-key `Obj.Meta`\" when the provider has none. When plugin-calls is present, a\n * \"Start video call\" action switches the article to the call surface and the chat moves to a companion.\n */\nexport const ChannelArticle = ({ role, subject: channel, attendableId, chatOnly }: ChannelArticleProps) => {\n const identity = useIdentity();\n const space = channel ? getSpace(channel) : undefined;\n const members = useMembers(space?.id);\n const id = channel ? Obj.getURI(channel) : undefined;\n const activity = useStatus(space, id);\n const { invokePromise } = Hooks.useOperationInvoker();\n\n const providers = Hooks.useCapabilities(ThreadCapabilities.ChannelBackend);\n const provider = channel ? ChannelBackend.resolveProvider(providers, channel.backend.kind) : undefined;\n const messages = useMessages(channel);\n const readOnly = channel ? (provider?.readOnly?.(channel) ?? Obj.getMeta(channel).keys.length > 0) : false;\n\n const callProvider = Hooks.useCapabilities(CallsCapabilities.CallTransportProvider)[0];\n const callManager = Hooks.useCapabilities(CallsCapabilities.Manager)[0];\n const joined = useAtomValue(callManager?.joinedAtom ?? NOT_JOINED);\n const currentRoomId = useAtomValue(callManager?.roomIdAtom ?? NO_ROOM);\n // `chatOnly` (the in-call chat companion) keeps showing messages so the call lives only in the primary.\n const inThisCall = !!id && joined && currentRoomId === id;\n const showCall = inThisCall && !chatOnly;\n const canStartCall = !!callProvider && !inThisCall;\n\n const handleStartCall = useCallback(async () => {\n if (!callProvider || !id) {\n return;\n }\n try {\n await callProvider.join(id);\n } catch (err) {\n // The menu action fires this without awaiting, so a failed join (e.g. the transport rejects\n // the room) must be reported here rather than surface as an unhandled rejection.\n log.catch(err);\n }\n }, [callProvider, id]);\n\n const menuActions = useMenuBuilder(() => {\n const builder = MenuBuilder.make().root({ label: ['channel-toolbar.title', { ns: meta.profile.key }] });\n if (canStartCall) {\n builder.action(\n 'start-video-call',\n { label: ['start-video-call.menu', { ns: meta.profile.key }], icon: 'ph--video-camera--regular' },\n () => {\n void handleStartCall();\n },\n );\n }\n return builder.build();\n }, [canStartCall, handleStartCall]);\n\n const handleSend = (text: string) => {\n if (!channel || !identity || readOnly) {\n return false;\n }\n\n void invokePromise(ThreadOperation.AppendChannelMessage, {\n channel,\n sender: { identityDid: identity.did },\n text,\n });\n\n return true;\n };\n\n if (!space || !channel || !id) {\n return null;\n }\n\n return (\n <Panel.Root role={role}>\n {canStartCall && (\n <Panel.Header>\n <ActionToolbar {...menuActions} attendableId={attendableId} />\n </Panel.Header>\n )}\n {showCall ? (\n <Panel.Body>\n <Surface.Surface type={AppSurface.Article} data={{ subject: { roomId: id }, attendableId }} limit={1} />\n </Panel.Body>\n ) : (\n <Panel.Body asChild>\n <MessageThread\n id={id}\n classNames='dx-document'\n identity={identity ?? undefined}\n members={members}\n messages={messages}\n activity={activity}\n onSend={handleSend}\n readOnly={readOnly}\n />\n </Panel.Body>\n )}\n </Panel.Root>\n );\n};\n\nChannelArticle.displayName = 'ChannelArticle';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA0BA,IAAM,aAAa,KAAK,KAAK,KAAK;AAClC,IAAM,UAAU,KAAK,KAAyB,KAAA,CAAS;;;;;;;;;AAoBvD,IAAa,kBAAkB,EAAE,MAAM,SAAS,SAAS,cAAc,eAAoC;CACzG,MAAM,WAAW,YAAY;CAC7B,MAAM,QAAQ,UAAU,SAAS,OAAO,IAAI,KAAA;CAC5C,MAAM,UAAU,WAAW,OAAO,EAAE;CACpC,MAAM,KAAK,UAAU,IAAI,OAAO,OAAO,IAAI,KAAA;CAC3C,MAAM,WAAW,UAAU,OAAO,EAAE;CACpC,MAAM,EAAE,kBAAkB,MAAM,oBAAoB;CAEpD,MAAM,YAAY,MAAM,gBAAgB,mBAAmB,cAAc;CACzE,MAAM,WAAW,UAAU,eAAe,gBAAgB,WAAW,QAAQ,QAAQ,IAAI,IAAI,KAAA;CAC7F,MAAM,WAAW,YAAY,OAAO;CACpC,MAAM,WAAW,UAAW,UAAU,WAAW,OAAO,KAAK,IAAI,QAAQ,OAAO,CAAC,CAAC,KAAK,SAAS,IAAK;CAErG,MAAM,eAAe,MAAM,gBAAgB,kBAAkB,qBAAqB,CAAC,CAAC;CACpF,MAAM,cAAc,MAAM,gBAAgB,kBAAkB,OAAO,CAAC,CAAC;CACrE,MAAM,SAAS,aAAa,aAAa,cAAc,UAAU;CACjE,MAAM,gBAAgB,aAAa,aAAa,cAAc,OAAO;CAErE,MAAM,aAAa,CAAC,CAAC,MAAM,UAAU,kBAAkB;CACvD,MAAM,WAAW,cAAc,CAAC;CAChC,MAAM,eAAe,CAAC,CAAC,gBAAgB,CAAC;CAExC,MAAM,kBAAkB,YAAY,YAAY;EAC9C,IAAI,CAAC,gBAAgB,CAAC,IACpB;EAEF,IAAI;GACF,MAAM,aAAa,KAAK,EAAE;EAC5B,SAAS,KAAK;GAGZ,IAAI,MAAM,KAAE,KAAA,GAAA;IAAA,YAAA;IAAA,GAAA;IAAA,GAAA;IAAA,GAAA,KAAA;GAAA,CAAC;EACf;CACF,GAAG,CAAC,cAAc,EAAE,CAAC;CAErB,MAAM,cAAc,qBAAqB;EACvC,MAAM,UAAU,YAAY,KAAK,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,yBAAyB,EAAE,IAAI,KAAK,QAAQ,IAAI,CAAC,EAAE,CAAC;EACtG,IAAI,cACF,QAAQ,OACN,oBACA;GAAE,OAAO,CAAC,yBAAyB,EAAE,IAAI,KAAK,QAAQ,IAAI,CAAC;GAAG,MAAM;EAA4B,SAC1F;GACJ,gBAAqB;EACvB,CACF;EAEF,OAAO,QAAQ,MAAM;CACvB,GAAG,CAAC,cAAc,eAAe,CAAC;CAElC,MAAM,cAAc,SAAiB;EACnC,IAAI,CAAC,WAAW,CAAC,YAAY,UAC3B,OAAO;EAGT,cAAmB,gBAAgB,sBAAsB;GACvD;GACA,QAAQ,EAAE,aAAa,SAAS,IAAI;GACpC;EACF,CAAC;EAED,OAAO;CACT;CAEA,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IACzB,OAAO;CAGT,OACE,qBAAC,MAAM,MAAP;EAAkB;EAAlB,UAAA,CACG,gBACC,oBAAC,MAAM,QAAP,EAAA,UACE,oBAAC,eAAD;GAAe,GAAI;GAA2B;EAAe,CAAA,EACjD,CAAA,GAEf,WACC,oBAAC,MAAM,MAAP,EAAA,UACE,oBAAC,QAAQ,SAAT;GAAiB,MAAM,WAAW;GAAS,MAAM;IAAE,SAAS,EAAE,QAAQ,GAAG;IAAG;GAAa;GAAG,OAAO;EAAI,CAAA,EAC7F,CAAA,IAEZ,oBAAC,MAAM,MAAP;GAAY,SAAA;GACV,UAAA,oBAAC,eAAD;IACM;IACJ,YAAW;IACX,UAAU,YAAY,KAAA;IACb;IACC;IACA;IACV,QAAQ;IACE;GACX,CAAA;EACS,CAAA,CAEJ;;AAEhB;AAEA,eAAe,cAAc"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ChannelBackend, ThreadCapabilities } from "#types";
|
|
2
2
|
import { useCallback, useMemo } from "react";
|
|
3
|
-
import { useCapabilities } from "@dxos/app-framework/ui";
|
|
4
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import * as Hooks from "@dxos/app-framework/Hooks";
|
|
5
5
|
import { Obj } from "@dxos/echo";
|
|
6
6
|
import { Form } from "@dxos/react-ui-form";
|
|
7
7
|
//#region src/containers/ChannelCreatePanel/ChannelCreatePanel.tsx
|
|
@@ -12,8 +12,8 @@ import { Form } from "@dxos/react-ui-form";
|
|
|
12
12
|
* selected provider's create fields (just a name field when there is a single
|
|
13
13
|
* field-less provider).
|
|
14
14
|
*/
|
|
15
|
-
var ChannelCreatePanel = ({ target, onCreateObject }) => {
|
|
16
|
-
const providers = useCapabilities(ThreadCapabilities.ChannelBackend);
|
|
15
|
+
var ChannelCreatePanel = ({ target, onCreateObject, onCancel }) => {
|
|
16
|
+
const providers = Hooks.useCapabilities(ThreadCapabilities.ChannelBackend);
|
|
17
17
|
const schema = useMemo(() => ChannelBackend.buildChannelFormSchema(providers), [providers]);
|
|
18
18
|
const handleSave = useCallback((values) => {
|
|
19
19
|
const { name, backend } = values;
|
|
@@ -30,8 +30,9 @@ var ChannelCreatePanel = ({ target, onCreateObject }) => {
|
|
|
30
30
|
schema,
|
|
31
31
|
defaultValues: {},
|
|
32
32
|
onSave: handleSave,
|
|
33
|
+
onCancel,
|
|
33
34
|
testId: "create-channel-form",
|
|
34
|
-
children: /* @__PURE__ */ jsx(Form.Viewport, { children: /* @__PURE__ */ jsxs(Form.Content, { children: [/* @__PURE__ */ jsx(Form.
|
|
35
|
+
children: /* @__PURE__ */ jsx(Form.Viewport, { children: /* @__PURE__ */ jsxs(Form.Content, { children: [/* @__PURE__ */ jsx(Form.Fields, {}), /* @__PURE__ */ jsx(Form.Actions, {})] }) })
|
|
35
36
|
});
|
|
36
37
|
};
|
|
37
38
|
ChannelCreatePanel.displayName = "ChannelCreatePanel";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-ChannelCreatePanel.mjs","names":[],"sources":["../../src/containers/ChannelCreatePanel/ChannelCreatePanel.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useMemo } from 'react';\n\nimport
|
|
1
|
+
{"version":3,"file":"chunk-ChannelCreatePanel.mjs","names":[],"sources":["../../src/containers/ChannelCreatePanel/ChannelCreatePanel.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useMemo } from 'react';\n\nimport * as Hooks from '@dxos/app-framework/Hooks';\nimport { Obj } from '@dxos/echo';\nimport type * as SpaceCapabilities from '@dxos/plugin-space/SpaceCapabilities';\nimport { Form } from '@dxos/react-ui-form';\n\nimport { ChannelBackend, ThreadCapabilities } from '#types';\n\n/**\n * Provider-driven create panel for channels. Reads the registered\n * `ChannelBackend` providers and renders a react-ui-form whose schema is the\n * assembled `{ name?, backend: Union(...) }` — a backend selector plus the\n * selected provider's create fields (just a name field when there is a single\n * field-less provider).\n */\nexport const ChannelCreatePanel = ({\n target,\n onCreateObject,\n onCancel,\n}: SpaceCapabilities.CreateObjectCustomPanelProps) => {\n const providers = Hooks.useCapabilities(ThreadCapabilities.ChannelBackend);\n const schema = useMemo(() => ChannelBackend.buildChannelFormSchema(providers), [providers]);\n\n const handleSave = useCallback(\n (values: { name?: string; backend?: { kind: string } & Record<string, unknown> }) => {\n const { name, backend } = values;\n const { kind, ...options } = backend ?? {};\n void onCreateObject({ name, kind, options });\n },\n [onCreateObject],\n );\n\n return (\n <Form.Root\n autoFocus\n db={Obj.isObject(target) ? Obj.getDatabase(target) : target}\n schema={schema}\n defaultValues={{}}\n onSave={handleSave}\n onCancel={onCancel}\n testId='create-channel-form'\n >\n <Form.Viewport>\n <Form.Content>\n <Form.Fields />\n <Form.Actions />\n </Form.Content>\n </Form.Viewport>\n </Form.Root>\n );\n};\n\nChannelCreatePanel.displayName = 'ChannelCreatePanel';\n"],"mappings":";;;;;;;;;;;;;;AAoBA,IAAa,sBAAsB,EACjC,QACA,gBACA,eACoD;CACpD,MAAM,YAAY,MAAM,gBAAgB,mBAAmB,cAAc;CACzE,MAAM,SAAS,cAAc,eAAe,uBAAuB,SAAS,GAAG,CAAC,SAAS,CAAC;CAE1F,MAAM,aAAa,aAChB,WAAoF;EACnF,MAAM,EAAE,MAAM,YAAY;EAC1B,MAAM,EAAE,MAAM,GAAG,YAAY,WAAW,CAAC;EACzC,eAAoB;GAAE;GAAM;GAAM;EAAQ,CAAC;CAC7C,GACA,CAAC,cAAc,CACjB;CAEA,OACE,oBAAC,KAAK,MAAN;EACE,WAAA;EACA,IAAI,IAAI,SAAS,MAAM,IAAI,IAAI,YAAY,MAAM,IAAI;EAC7C;EACR,eAAe,CAAC;EAChB,QAAQ;EACE;EACV,QAAO;EAEP,UAAA,oBAAC,KAAK,UAAN,EAAA,UACE,qBAAC,KAAK,SAAN,EAAA,UAAA,CACE,oBAAC,KAAK,QAAN,CAAc,CAAA,GACd,oBAAC,KAAK,SAAN,CAAe,CAAA,CACH,EAAA,CAAA,EACD,CAAA;CACN,CAAA;AAEf;AAEA,mBAAmB,cAAc"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
//#region PLUGIN.mdl?raw
|
|
2
|
+
var PLUGIN_default = "---\nid: org.dxos.plugin.thread\nname: ThreadPlugin\nversion: 0.1.0\n---\n\nThreadPlugin provides chat: channels backed by an ECHO feed and free-standing message threads.\nIt renders the channel article + companion surfaces and a thread surface, and contributes the\noperations that create a channel and append messages. Shared message/thread UI comes from\n`@dxos/react-ui-thread`, and the `Channel`/`Message`/`Thread` schema comes from `@dxos/types`.\nDocument comments and the comment-thread AI agent live in `@dxos/plugin-comments`.\n\n## Extensions\n\nThe following extension dialects are used in this document.\n\n| Term | URI |\n|-------------|--------------------------------|\n| `type` | `org.dxos.mdl.type@1.0` |\n| `feat` | `org.dxos.mdl.feat@1.0` |\n| `op` | `org.dxos.mdl.op@1.1` |\n| `test` | `org.dxos.mdl.test@1.0` |\n\n## Types\n\n```mdl\ntype Channel\n desc: |\n A chat channel. Defined in @dxos/types. Carries an optional `feed` Ref whose\n queue holds the channel's Message objects in order.\n```\n\n## Operations\n\n```mdl\nop OnCreateSpace\n key: org.dxos.plugin.thread.operation.onCreateSpace\n desc: On space creation, create a default \"General\" channel in the root collection.\n```\n\n```mdl\nop CreateChannel\n key: org.dxos.operation.thread.createChannel\n desc: Create a new Channel in the given space.\n in:\n spaceId: SpaceId\n name?: String\n out:\n object: Channel\n```\n\n```mdl\nop AppendChannelMessage\n key: org.dxos.operation.thread.appendChannelMessage\n desc: Append a Message authored by `sender` to the channel's feed.\n in:\n channel: Channel\n sender: Actor\n text: String\n```\n\n```mdl\nop SendToChannel\n key: org.dxos.operation.thread.sendToChannel\n desc: |\n Send text to a channel, or to a backend thread inside it, through the provider resolved by\n `channel.backend.kind`. A backend refusal returns `delivered: false` with a reason; a missing\n provider or a backend without threads fails with a typed error.\n in:\n channel: Ref<Channel>\n thread?: String\n text: String\n out:\n delivered: Boolean\n messageIds?: String[]\n properties?: Record\n reason?: String\n```\n\n```mdl\nop OpenDirect\n key: org.dxos.operation.thread.openDirect\n desc: |\n Open a direct conversation (a DM) with a Person through the channel's account, via the\n backend's optional `openDirect`; returns a thread id for SendToChannel.\n in:\n channel: Ref<Channel>\n person: Ref<Person>\n out:\n thread?: String\n reason?: String\n```\n\n```mdl\nop ConnectChannel\n key: org.dxos.operation.thread.connectChannel\n desc: Start the backend's optional connection (a bot gateway); DisconnectChannel and GetChannelStatus stop and report it.\n in:\n channel: Ref<Channel>\n out:\n status: ConnectionStatus\n```\n\n## Features\n\n```mdl\nfeat F-1: Channel chat\n req F-1.1: A Channel article MUST render its feed messages newest-last with a\n pinned composer; sending invokes AppendChannelMessage.\n req F-1.2: Externally-synced channels (those carrying foreign-key Obj.Meta) MUST\n render read-only — the composer is suppressed.\n```\n\n```mdl\nfeat F-2: Thread chat\n req F-2.1: A Thread article MUST render the thread's messages and append new\n messages by pushing onto `thread.messages`.\n```\n\n## QA\n\nExecutable tests. Each step carries a human instruction (`do`) and, where the step maps to an\ninvocable operation, an agent binding (`invoke`). Report failures by test and step number.\n\n```mdl\ntest QA-1: Create a channel and send a message\n desc: The core thread round-trip — create a Channel, send a message, read it back from the feed.\n actors: both\n covers: [F-1.1]\n status: unverified\n given:\n - identityDid: an identity exists, its DID used as the message `sender`\n - space: a space is open\n - no Channel named \"QA Channel\" exists — ABORT rather than deleting one this test did not create\n steps:\n - name: Create the channel\n do: In the navtree, click + on the space and choose Channel. Name it \"QA Channel\".\n invoke: [op:CreateChannel] { spaceId: $given.space.id, name: \"QA Channel\" }\n capture: created\n expect: a Channel named \"QA Channel\" now exists and opens in the channel article\n assert: return !!$created.object\n - name: Place it in the space\n do: (no separate gesture — the navtree create action places it)\n invoke: org.dxos.operation.space.addObject { object: $created.object, target: $given.space }\n expect: \"QA Channel\" appears as a row in the navtree\n - name: Send a message\n do: In the composer at the bottom of the channel article, type \"Hello QA\" and press Enter.\n invoke: |\n org.dxos.operation.thread.appendChannelMessage {\n channel: $created.object,\n sender: { identityDid: $given.identityDid },\n text: \"Hello QA\"\n }\n expect: \"Hello QA\" appears as the newest (bottom-most) message in the feed\n note: |\n `output: void` — Rule 3 applies: verify the effect, not the return value. Reading the\n feed's queue is not expressible as a synchronous DOM/db snippet here, so this step is\n judged by `expect` alone.\n after:\n - name: Delete the channel\n do: Right-click \"QA Channel\" in the navtree and choose Delete.\n invoke: org.dxos.operation.space.removeObjects { objects: [$created.object], target: $given.space }\n expect: the row leaves the navtree and its plank closes if it was open\n```\n\n```mdl\ntest QA-2: Default \"General\" channel on space creation\n desc: The lifecycle hook that seeds every new space with a channel — no user gesture involved.\n actors: agent\n covers: []\n status: unverified\n given:\n - an identity exists\n steps:\n - name: Create a new space\n do: Click \"Create space\" (or invoke the equivalent action).\n invoke: org.dxos.operation.space.create {}\n capture: created\n expect: a new space is created\n assert: return !!$created.space\n - name: Confirm the default channel exists\n do: Open the new space's navtree and look for a \"General\" channel.\n expect: a Channel named \"General\" exists in the root collection of the new space\n note: |\n NO separate `invoke` — `org.dxos.plugin.thread.operation.onCreateSpace` is a lifecycle\n hook the space-creation pipeline runs itself, not something this test calls directly; this\n step only verifies the effect.\n assert: |\n return (await $created.space.db.query(dxos.Filter.type(Channel)).run())\n .objects.some((c) => c.name === 'General');\n after:\n - name: Delete the space\n do: Right-click the new space in the navtree and choose Delete space.\n invoke: org.dxos.operation.space.delete { space: $created.space }\n expect: the space leaves the navtree\n```\n";
|
|
3
|
+
//#endregion
|
|
4
|
+
export { PLUGIN_default as t };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=chunk-PLUGIN.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-PLUGIN.mjs","names":[],"sources":[],"mappings":""}
|
|
@@ -1,25 +1,30 @@
|
|
|
1
|
-
import { useStatus } from "#hooks";
|
|
2
|
-
import { Message } from "@dxos/types";
|
|
3
1
|
import { useMemo } from "react";
|
|
4
|
-
import
|
|
5
|
-
import { isNonNullable } from "@dxos/util";
|
|
2
|
+
import * as Util from "@dxos/react-ui/Util";
|
|
6
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
4
|
import { Obj, Ref } from "@dxos/echo";
|
|
5
|
+
import { Message } from "@dxos/types";
|
|
6
|
+
import { useAtomValue } from "@effect/atom-react/Hooks";
|
|
7
|
+
import * as Atom from "effect/reactivity/Atom";
|
|
8
8
|
import { useIdentity, useMembers } from "@dxos/halo-react";
|
|
9
9
|
import { getSpace } from "@dxos/react-client/echo";
|
|
10
|
+
import * as Panel from "@dxos/react-ui/Panel";
|
|
10
11
|
import { MessageThread } from "#components";
|
|
12
|
+
import { useStatus } from "#hooks";
|
|
11
13
|
//#region src/containers/ThreadArticle/ThreadArticle.tsx
|
|
12
14
|
/**
|
|
13
15
|
* Renders an AutoMerge {@link Thread} as a chat: appends new messages by pushing
|
|
14
16
|
* onto `thread.messages`. Used for comment threads and the meeting in-call chat.
|
|
15
17
|
*/
|
|
16
|
-
var ThreadArticle = composable(({ thread, context, autoFocus, current, ...props }, forwardedRef) => {
|
|
18
|
+
var ThreadArticle = Util.composable(({ thread, context, autoFocus, current, ...props }, forwardedRef) => {
|
|
17
19
|
const space = getSpace(thread);
|
|
18
20
|
const id = Obj.getURI(thread);
|
|
19
21
|
const identity = useIdentity();
|
|
20
22
|
const members = useMembers(space?.id);
|
|
21
23
|
const activity = useStatus(space, id);
|
|
22
|
-
const messages = useMemo(() =>
|
|
24
|
+
const messages = useAtomValue(useMemo(() => Atom.make((get) => (get(Obj.atomProperty(thread, "messages")) ?? []).flatMap((message) => {
|
|
25
|
+
const value = get(message.atom);
|
|
26
|
+
return value ? [value] : [];
|
|
27
|
+
})), [thread]));
|
|
23
28
|
const handleSend = (text) => {
|
|
24
29
|
Obj.update(thread, (thread) => {
|
|
25
30
|
thread.messages.push(Ref.make(Obj.make(Message.Message, {
|
|
@@ -35,10 +40,10 @@ var ThreadArticle = composable(({ thread, context, autoFocus, current, ...props
|
|
|
35
40
|
return true;
|
|
36
41
|
};
|
|
37
42
|
if (!space) return null;
|
|
38
|
-
return /* @__PURE__ */ jsxs(Panel.Root, { children: [/* @__PURE__ */ jsx(Panel.
|
|
43
|
+
return /* @__PURE__ */ jsxs(Panel.Root, { children: [/* @__PURE__ */ jsx(Panel.Header, {}), /* @__PURE__ */ jsx(Panel.Body, {
|
|
39
44
|
asChild: true,
|
|
40
45
|
children: /* @__PURE__ */ jsx(MessageThread, {
|
|
41
|
-
...composableProps(props),
|
|
46
|
+
...Util.composableProps(props),
|
|
42
47
|
id,
|
|
43
48
|
identity,
|
|
44
49
|
members,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-ThreadArticle.mjs","names":[],"sources":["../../src/containers/ThreadArticle/ThreadArticle.tsx"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { useMemo } from 'react';\n\nimport { Obj, Ref } from '@dxos/echo';\nimport { useIdentity, useMembers } from '@dxos/halo-react';\nimport { getSpace } from '@dxos/react-client/echo';\nimport {
|
|
1
|
+
{"version":3,"file":"chunk-ThreadArticle.mjs","names":[],"sources":["../../src/containers/ThreadArticle/ThreadArticle.tsx"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport { useAtomValue } from '@effect/atom-react/Hooks';\nimport * as Atom from 'effect/reactivity/Atom';\nimport React, { useMemo } from 'react';\n\nimport { Obj, Ref } from '@dxos/echo';\nimport { useIdentity, useMembers } from '@dxos/halo-react';\nimport { getSpace } from '@dxos/react-client/echo';\nimport { type ThreadContentProps } from '@dxos/react-ui-thread';\nimport * as Panel from '@dxos/react-ui/Panel';\nimport * as Util from '@dxos/react-ui/Util';\nimport { Message, type Thread } from '@dxos/types';\n\nimport { MessageThread } from '#components';\nimport { useStatus } from '#hooks';\n\nexport type ThreadArticleProps = Util.ThemedClassName<\n {\n thread: Thread.Thread;\n context?: Obj.Unknown;\n autoFocus?: boolean;\n } & Pick<ThreadContentProps, 'current'>\n>;\n\n/**\n * Renders an AutoMerge {@link Thread} as a chat: appends new messages by pushing\n * onto `thread.messages`. Used for comment threads and the meeting in-call chat.\n */\nexport const ThreadArticle = Util.composable<HTMLDivElement, ThreadArticleProps>(\n ({ thread, context, autoFocus, current, ...props }, forwardedRef) => {\n // Members and presence are space-scoped; a thread outside a space has nothing to resolve against.\n const space = getSpace(thread);\n const id = Obj.getURI(thread);\n const identity = useIdentity()!;\n const members = useMembers(space?.id);\n const activity = useStatus(space, id);\n\n const messages = useAtomValue(\n useMemo(\n () =>\n Atom.make((get) =>\n (get(Obj.atomProperty(thread, 'messages')) ?? []).flatMap((message) => {\n const value = get(message.atom);\n return value ? [value] : [];\n }),\n ),\n [thread],\n ),\n );\n\n const handleSend = (text: string) => {\n Obj.update(thread, (thread) => {\n thread.messages.push(\n Ref.make(\n Obj.make(Message.Message, {\n created: new Date().toISOString(),\n sender: { identityDid: identity.did },\n blocks: [{ _tag: 'text', text }],\n properties: context ? { context: Ref.make(context) } : undefined,\n }),\n ),\n );\n });\n return true;\n };\n\n if (!space) {\n return null;\n }\n\n return (\n <Panel.Root>\n <Panel.Header></Panel.Header>\n <Panel.Body asChild>\n <MessageThread\n {...Util.composableProps(props)}\n id={id}\n identity={identity}\n members={members}\n messages={messages}\n activity={activity}\n onSend={handleSend}\n autoFocus={autoFocus}\n current={current}\n ref={forwardedRef}\n />\n </Panel.Body>\n </Panel.Root>\n );\n },\n);\n\nThreadArticle.displayName = 'ThreadArticle';\n"],"mappings":";;;;;;;;;;;;;;;;;AA+BA,IAAa,gBAAgB,KAAK,YAC/B,EAAE,QAAQ,SAAS,WAAW,SAAS,GAAG,SAAS,iBAAiB;CAEnE,MAAM,QAAQ,SAAS,MAAM;CAC7B,MAAM,KAAK,IAAI,OAAO,MAAM;CAC5B,MAAM,WAAW,YAAY;CAC7B,MAAM,UAAU,WAAW,OAAO,EAAE;CACpC,MAAM,WAAW,UAAU,OAAO,EAAE;CAEpC,MAAM,WAAW,aACf,cAEI,KAAK,MAAM,SACR,IAAI,IAAI,aAAa,QAAQ,UAAU,CAAC,KAAK,CAAC,EAAA,CAAG,SAAS,YAAY;EACrE,MAAM,QAAQ,IAAI,QAAQ,IAAI;EAC9B,OAAO,QAAQ,CAAC,KAAK,IAAI,CAAC;CAC5B,CAAC,CACH,GACF,CAAC,MAAM,CACT,CACF;CAEA,MAAM,cAAc,SAAiB;EACnC,IAAI,OAAO,SAAS,WAAW;GAC7B,OAAO,SAAS,KACd,IAAI,KACF,IAAI,KAAK,QAAQ,SAAS;IACxB,0BAAS,IAAI,KAAK,EAAA,CAAE,YAAY;IAChC,QAAQ,EAAE,aAAa,SAAS,IAAI;IACpC,QAAQ,CAAC;KAAE,MAAM;KAAQ;IAAK,CAAC;IAC/B,YAAY,UAAU,EAAE,SAAS,IAAI,KAAK,OAAO,EAAE,IAAI,KAAA;GACzD,CAAC,CACH,CACF;EACF,CAAC;EACD,OAAO;CACT;CAEA,IAAI,CAAC,OACH,OAAO;CAGT,OACE,qBAAC,MAAM,MAAP,EAAA,UAAA,CACE,oBAAC,MAAM,QAAP,CAA4B,CAAA,GAC5B,oBAAC,MAAM,MAAP;EAAY,SAAA;EACV,UAAA,oBAAC,eAAD;GACE,GAAI,KAAK,gBAAgB,KAAK;GAC1B;GACM;GACD;GACC;GACA;GACV,QAAQ;GACG;GACF;GACT,KAAK;EACN,CAAA;CACS,CAAA,CACF,EAAA,CAAA;AAEhB,CACF;AAEA,cAAc,cAAc"}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
import { n as getChannelsPath } from "./chunk-paths.mjs";
|
|
2
1
|
import * as Capability from "@dxos/app-framework/Capability";
|
|
3
2
|
import { meta } from "#meta";
|
|
4
|
-
import * as GraphPath from "@dxos/app-toolkit/GraphPath";
|
|
5
|
-
import { Channel } from "@dxos/types";
|
|
6
|
-
import { Position } from "@dxos/util";
|
|
7
3
|
import * as Operation from "@dxos/compute/Operation";
|
|
8
4
|
import { Obj, Type } from "@dxos/echo";
|
|
5
|
+
import { Channel } from "@dxos/types";
|
|
9
6
|
import * as Effect from "effect/Effect";
|
|
10
7
|
import * as AppGraphBuilder from "@dxos/app-graph/AppGraphBuilder";
|
|
11
8
|
import * as AppCapabilities from "@dxos/app-toolkit/AppCapabilities";
|
|
12
9
|
import * as AppNode from "@dxos/app-toolkit/AppNode";
|
|
13
10
|
import * as AppNodeMatcher from "@dxos/app-toolkit/AppNodeMatcher";
|
|
11
|
+
import * as GraphPath from "@dxos/app-toolkit/GraphPath";
|
|
14
12
|
import * as TypeSection from "@dxos/app-toolkit/TypeSection";
|
|
15
13
|
import * as CallsCapabilities from "@dxos/plugin-calls/CallsCapabilities";
|
|
16
14
|
import * as SpaceOperation from "@dxos/plugin-space/SpaceOperation";
|
|
15
|
+
import * as Position from "@dxos/util/Position";
|
|
16
|
+
//#region src/paths.ts
|
|
17
|
+
var { getSectionPath: getChannelsPath, getObjectPath: getChannelPath } = GraphPath.createTypeSectionPaths(Channel.Channel, { groupId: GraphPath.GroupSegments.communications });
|
|
18
|
+
//#endregion
|
|
17
19
|
//#region src/capabilities/app-graph-builder.ts
|
|
18
20
|
var channelTypename = Type.getTypename(Channel.Channel);
|
|
19
21
|
var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function* () {
|
|
@@ -29,6 +31,7 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
|
|
|
29
31
|
})
|
|
30
32
|
}), AppGraphBuilder.createTypeExtension({
|
|
31
33
|
id: "channelChatCompanion",
|
|
34
|
+
relation: AppNode.companion,
|
|
32
35
|
type: Channel.Channel,
|
|
33
36
|
connector: (channel, get) => {
|
|
34
37
|
const [callManager] = get(callManagerAtom);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-app-graph-builder.mjs","names":[],"sources":["../../src/capabilities/app-graph-builder.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraphBuilder from '@dxos/app-graph/AppGraphBuilder';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport * as AppNode from '@dxos/app-toolkit/AppNode';\nimport * as AppNodeMatcher from '@dxos/app-toolkit/AppNodeMatcher';\nimport * as GraphPath from '@dxos/app-toolkit/GraphPath';\nimport * as TypeSection from '@dxos/app-toolkit/TypeSection';\nimport * as Operation from '@dxos/compute/Operation';\nimport { Obj, Type } from '@dxos/echo';\nimport * as CallsCapabilities from '@dxos/plugin-calls/CallsCapabilities';\nimport * as SpaceOperation from '@dxos/plugin-space/SpaceOperation';\nimport { Channel } from '@dxos/types';\nimport
|
|
1
|
+
{"version":3,"file":"chunk-app-graph-builder.mjs","names":[],"sources":["../../src/paths.ts","../../src/capabilities/app-graph-builder.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as GraphPath from '@dxos/app-toolkit/GraphPath';\nimport { Channel } from '@dxos/types';\n\nconst { getSectionPath: getChannelsPath, getObjectPath: getChannelPath } = GraphPath.createTypeSectionPaths(\n Channel.Channel,\n { groupId: GraphPath.GroupSegments.communications },\n);\n\nexport { getChannelPath, getChannelsPath };\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraphBuilder from '@dxos/app-graph/AppGraphBuilder';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport * as AppNode from '@dxos/app-toolkit/AppNode';\nimport * as AppNodeMatcher from '@dxos/app-toolkit/AppNodeMatcher';\nimport * as GraphPath from '@dxos/app-toolkit/GraphPath';\nimport * as TypeSection from '@dxos/app-toolkit/TypeSection';\nimport * as Operation from '@dxos/compute/Operation';\nimport { Obj, Type } from '@dxos/echo';\nimport * as CallsCapabilities from '@dxos/plugin-calls/CallsCapabilities';\nimport * as SpaceOperation from '@dxos/plugin-space/SpaceOperation';\nimport { Channel } from '@dxos/types';\nimport * as Position from '@dxos/util/Position';\n\nimport { meta } from '#meta';\n\nimport { getChannelsPath } from '../paths.ts';\n\nconst channelTypename = Type.getTypename(Channel.Channel);\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n // Read reactively so the extension establishes a dependency and heals once this\n // capability lands (dependency modules contribute individually, not batched per wave).\n const callManagerAtom = yield* Capability.atom(CallsCapabilities.Manager);\n\n const extensions = yield* Effect.all([\n TypeSection.createTypeSectionExtension(Channel.Channel, {\n urlKey: 'channel',\n match: AppNodeMatcher.whenNavTreeGroup(GraphPath.GroupTypes.communications),\n groupSegment: GraphPath.GroupSegments.communications,\n createObject: (space) =>\n Operation.invoke(SpaceOperation.OpenObjectForm, {\n target: space.db,\n typename: channelTypename,\n targetNodeId: getChannelsPath(space.db.spaceId),\n }),\n }),\n\n AppGraphBuilder.createTypeExtension({\n id: 'channelChatCompanion',\n relation: AppNode.companion,\n type: Channel.Channel,\n connector: (channel, get) => {\n const [callManager] = get(callManagerAtom);\n if (!callManager) {\n return Effect.succeed([]);\n }\n const joined = get(callManager.joinedAtom);\n const roomId = get(callManager.roomIdAtom);\n if (!joined || roomId !== Obj.getURI(channel)) {\n return Effect.succeed([]);\n }\n\n return Effect.succeed([\n AppNode.makeCompanion({\n variant: 'chat',\n label: ['channel-companion.label', { ns: meta.profile.key }],\n icon: 'ph--hash--regular',\n data: 'chat',\n position: Position.first,\n }),\n ]);\n },\n }),\n ]);\n\n return Capability.contribute(AppCapabilities.AppGraphBuilder, extensions);\n }),\n);\n"],"mappings":";;;;;;;;;;;;;;;;AAOA,IAAM,EAAE,gBAAgB,iBAAiB,eAAe,mBAAmB,UAAU,uBACnF,QAAQ,SACR,EAAE,SAAS,UAAU,cAAc,eAAe,CACpD;;;ACcA,IAAM,kBAAkB,KAAK,YAAY,QAAQ,OAAO;AAExD,IAAA,4BAAe,WAAW,WACxB,OAAO,WAAW,aAAa;CAG7B,MAAM,kBAAkB,OAAO,WAAW,KAAK,kBAAkB,OAAO;CAExE,MAAM,aAAa,OAAO,OAAO,IAAI,CACnC,YAAY,2BAA2B,QAAQ,SAAS;EACtD,QAAQ;EACR,OAAO,eAAe,iBAAiB,UAAU,WAAW,cAAc;EAC1E,cAAc,UAAU,cAAc;EACtC,eAAe,UACb,UAAU,OAAO,eAAe,gBAAgB;GAC9C,QAAQ,MAAM;GACd,UAAU;GACV,cAAc,gBAAgB,MAAM,GAAG,OAAO;EAChD,CAAC;CACL,CAAC,GAED,gBAAgB,oBAAoB;EAClC,IAAI;EACJ,UAAU,QAAQ;EAClB,MAAM,QAAQ;EACd,YAAY,SAAS,QAAQ;GAC3B,MAAM,CAAC,eAAe,IAAI,eAAe;GACzC,IAAI,CAAC,aACH,OAAO,OAAO,QAAQ,CAAC,CAAC;GAE1B,MAAM,SAAS,IAAI,YAAY,UAAU;GACzC,MAAM,SAAS,IAAI,YAAY,UAAU;GACzC,IAAI,CAAC,UAAU,WAAW,IAAI,OAAO,OAAO,GAC1C,OAAO,OAAO,QAAQ,CAAC,CAAC;GAG1B,OAAO,OAAO,QAAQ,CACpB,QAAQ,cAAc;IACpB,SAAS;IACT,OAAO,CAAC,2BAA2B,EAAE,IAAI,KAAK,QAAQ,IAAI,CAAC;IAC3D,MAAM;IACN,MAAM;IACN,UAAU,SAAS;GACrB,CAAC,CACH,CAAC;EACH;CACF,CAAC,CACH,CAAC;CAED,OAAO,WAAW,WAAW,gBAAgB,iBAAiB,UAAU;AAC1E,CAAC,CACH"}
|
|
@@ -1,21 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ChannelBackend, ThreadCapabilities, ThreadOperation } from "#types";
|
|
3
|
-
import { Message } from "@dxos/types";
|
|
1
|
+
import { ChannelBackend, ThreadOperation } from "#types";
|
|
4
2
|
import * as Operation from "@dxos/compute/Operation";
|
|
3
|
+
import { Message } from "@dxos/types";
|
|
5
4
|
import * as Effect from "effect/Effect";
|
|
6
|
-
import { invariant } from "@dxos/invariant";
|
|
7
5
|
//#region src/operations/append-channel-message.ts
|
|
8
|
-
var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/operations/append-channel-message.ts";
|
|
9
6
|
var handler = ThreadOperation.AppendChannelMessage.pipe(Operation.withHandler(Effect.fnUntraced(function* ({ channel, sender, text }) {
|
|
10
|
-
const
|
|
11
|
-
const provider = ChannelBackend.resolveProvider(providers, channel.backend.kind);
|
|
12
|
-
invariant(provider, `No channel backend for kind: ${channel.backend.kind}`, {
|
|
13
|
-
"~LogMeta": "~LogMeta",
|
|
14
|
-
F: __dxlog_file,
|
|
15
|
-
L: 20,
|
|
16
|
-
S: this,
|
|
17
|
-
A: ["provider", "`No channel backend for kind: ${channel.backend.kind}`"]
|
|
18
|
-
});
|
|
7
|
+
const provider = yield* ChannelBackend.getProvider(channel);
|
|
19
8
|
const message = Message.make({
|
|
20
9
|
sender,
|
|
21
10
|
blocks: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-append-channel-message.mjs","names":[],"sources":["../../src/operations/append-channel-message.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as
|
|
1
|
+
{"version":3,"file":"chunk-append-channel-message.mjs","names":[],"sources":["../../src/operations/append-channel-message.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Operation from '@dxos/compute/Operation';\nimport { Message } from '@dxos/types';\n\nimport { ChannelBackend, ThreadOperation } from '#types';\n\nconst handler: Operation.WithHandler<typeof ThreadOperation.AppendChannelMessage> =\n ThreadOperation.AppendChannelMessage.pipe(\n Operation.withHandler(\n Effect.fnUntraced(function* ({ channel, sender, text }) {\n const provider = yield* ChannelBackend.getProvider(channel);\n\n const message = Message.make({\n sender,\n blocks: [{ _tag: 'text', text }],\n });\n yield* provider.send(channel, message);\n }),\n ),\n );\n\nexport default handler;\n"],"mappings":";;;;;AAWA,IAAM,UACJ,gBAAgB,qBAAqB,KACnC,UAAU,YACR,OAAO,WAAW,WAAW,EAAE,SAAS,QAAQ,QAAQ;CACtD,MAAM,WAAW,OAAO,eAAe,YAAY,OAAO;CAE1D,MAAM,UAAU,QAAQ,KAAK;EAC3B;EACA,QAAQ,CAAC;GAAE,MAAM;GAAQ;EAAK,CAAC;CACjC,CAAC;CACD,OAAO,SAAS,KAAK,SAAS,OAAO;AACvC,CAAC,CACH,CACF"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import * as Capability from "@dxos/app-framework/Capability";
|
|
2
|
-
import { ThreadCapabilities } from "#types";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import * as Schema from "effect/Schema";
|
|
2
|
+
import { ChannelBackend, ThreadCapabilities } from "#types";
|
|
3
|
+
import { Database, Feed, Obj } from "@dxos/echo";
|
|
4
|
+
import { Channel } from "@dxos/types";
|
|
6
5
|
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Schema from "effect/Schema";
|
|
7
7
|
import { invariant } from "@dxos/invariant";
|
|
8
|
-
import * as ClientCapabilities from "@dxos/plugin-client/ClientCapabilities";
|
|
9
8
|
//#region src/capabilities/channel-backend-feed.ts
|
|
10
9
|
var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/capabilities/channel-backend-feed.ts";
|
|
11
10
|
/**
|
|
@@ -26,35 +25,26 @@ var feedChannelBackend = {
|
|
|
26
25
|
onMessages([]);
|
|
27
26
|
return () => {};
|
|
28
27
|
}
|
|
29
|
-
|
|
30
|
-
return result.subscribe(() => onMessages(result.results), { fire: true });
|
|
28
|
+
return ChannelBackend.subscribeFeed(db, feed, onMessages);
|
|
31
29
|
},
|
|
32
30
|
send: (channel, message) => Effect.gen(function* () {
|
|
33
31
|
const db = Obj.getDatabase(channel);
|
|
34
32
|
invariant(db, "Database not found", {
|
|
35
33
|
"~LogMeta": "~LogMeta",
|
|
36
34
|
F: __dxlog_file,
|
|
37
|
-
L:
|
|
35
|
+
L: 39,
|
|
38
36
|
S: this,
|
|
39
37
|
A: ["db", "'Database not found'"]
|
|
40
38
|
});
|
|
41
|
-
const space = (yield* Capability.get(ClientCapabilities.Client)).spaces.get(db.spaceId);
|
|
42
|
-
invariant(space, "Space not found", {
|
|
43
|
-
"~LogMeta": "~LogMeta",
|
|
44
|
-
F: __dxlog_file,
|
|
45
|
-
L: 44,
|
|
46
|
-
S: this,
|
|
47
|
-
A: ["space", "'Space not found'"]
|
|
48
|
-
});
|
|
49
39
|
const feed = Channel.getFeed(channel);
|
|
50
40
|
invariant(feed, "Channel is not feed-backed", {
|
|
51
41
|
"~LogMeta": "~LogMeta",
|
|
52
42
|
F: __dxlog_file,
|
|
53
|
-
L:
|
|
43
|
+
L: 41,
|
|
54
44
|
S: this,
|
|
55
45
|
A: ["feed", "'Channel is not feed-backed'"]
|
|
56
46
|
});
|
|
57
|
-
yield* Feed.append(feed, [message]).pipe(Effect.provide(Database.layer(
|
|
47
|
+
yield* Feed.append(feed, [message]).pipe(Effect.provide(Database.layer(db)));
|
|
58
48
|
}),
|
|
59
49
|
readOnly: (channel) => Obj.getMeta(channel).keys.length > 0
|
|
60
50
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-channel-backend-feed.mjs","names":[],"sources":["../../src/capabilities/channel-backend-feed.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Schema from 'effect/Schema';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport { Database, Feed,
|
|
1
|
+
{"version":3,"file":"chunk-channel-backend-feed.mjs","names":[],"sources":["../../src/capabilities/channel-backend-feed.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Schema from 'effect/Schema';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport { Database, Feed, Obj } from '@dxos/echo';\nimport { invariant } from '@dxos/invariant';\nimport { Channel } from '@dxos/types';\n\nimport { ChannelBackend, ThreadCapabilities } from '#types';\n\n/**\n * Default local ECHO-feed-backed channel provider. Stores messages in a `Feed`\n * (`makeConfig` → `Feed.make()`), reads them via a reactive database query, and\n * writes via `Feed.append`. This is the backend `Channel.make()` defaults to.\n */\nexport const feedChannelBackend: ThreadCapabilities.ChannelBackendProvider = {\n kind: Channel.FeedBackendKind,\n label: 'Feed',\n icon: 'ph--rows--regular',\n createFields: Schema.Struct({}),\n makeConfig: () => Feed.make(),\n subscribe: (channel, onMessages) => {\n const feed = Channel.getFeed(channel);\n const db = Obj.getDatabase(channel);\n if (!feed || !db) {\n onMessages([]);\n return () => {};\n }\n\n return ChannelBackend.subscribeFeed(db, feed, onMessages);\n },\n send: (channel, message) =>\n Effect.gen(function* () {\n const db = Obj.getDatabase(channel);\n invariant(db, 'Database not found');\n const feed = Channel.getFeed(channel);\n invariant(feed, 'Channel is not feed-backed');\n yield* Feed.append(feed, [message]).pipe(Effect.provide(Database.layer(db)));\n }),\n readOnly: (channel) => Obj.getMeta(channel).keys.length > 0,\n};\n\n/** Contributes the default feed-backed channel provider. */\nexport const ChannelBackendFeed = Capability.makeModule(\n Effect.fnUntraced(function* () {\n return Capability.contribute(ThreadCapabilities.ChannelBackend, feedChannelBackend);\n }),\n);\n\nexport default ChannelBackendFeed;\n"],"mappings":";;;;;;;;;;;;;;AAmBA,IAAa,qBAAgE;CAC3E,MAAM,QAAQ;CACd,OAAO;CACP,MAAM;CACN,cAAc,OAAO,OAAO,CAAC,CAAC;CAC9B,kBAAkB,KAAK,KAAK;CAC5B,YAAY,SAAS,eAAe;EAClC,MAAM,OAAO,QAAQ,QAAQ,OAAO;EACpC,MAAM,KAAK,IAAI,YAAY,OAAO;EAClC,IAAI,CAAC,QAAQ,CAAC,IAAI;GAChB,WAAW,CAAC,CAAC;GACb,aAAa,CAAC;EAChB;EAEA,OAAO,eAAe,cAAc,IAAI,MAAM,UAAU;CAC1D;CACA,OAAO,SAAS,YACd,OAAO,IAAI,aAAa;EACtB,MAAM,KAAK,IAAI,YAAY,OAAO;EAClC,UAAU,IAAI,sBAAmB;GAAA,YAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA,CAAA,MAAA,sBAAA;EAAA,CAAC;EAClC,MAAM,OAAO,QAAQ,QAAQ,OAAO;EACpC,UAAU,MAAM,8BAA2B;GAAA,YAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA,CAAA,QAAA,8BAAA;EAAA,CAAC;EAC5C,OAAO,KAAK,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,QAAQ,SAAS,MAAM,EAAE,CAAC,CAAC;CAC7E,CAAC;CACH,WAAW,YAAY,IAAI,QAAQ,OAAO,CAAC,CAAC,KAAK,SAAS;AAC5D;;AAGA,IAAa,qBAAqB,WAAW,WAC3C,OAAO,WAAW,aAAa;CAC7B,OAAO,WAAW,WAAW,mBAAmB,gBAAgB,kBAAkB;AACpF,CAAC,CACH"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ChannelBackend, ThreadOperation } from "#types";
|
|
2
|
+
import * as Operation from "@dxos/compute/Operation";
|
|
3
|
+
import { Database } from "@dxos/echo";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
//#region src/operations/connect-channel.ts
|
|
6
|
+
var handler = ThreadOperation.ConnectChannel.pipe(Operation.withHandler(Effect.fnUntraced(function* ({ channel: channelRef }) {
|
|
7
|
+
const channel = yield* Database.load(channelRef);
|
|
8
|
+
const provider = yield* ChannelBackend.getProvider(channel);
|
|
9
|
+
return { status: yield* (yield* ChannelBackend.requireMember(provider, "connection")).start(channel) };
|
|
10
|
+
})));
|
|
11
|
+
//#endregion
|
|
12
|
+
export { handler as default };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=chunk-connect-channel.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-connect-channel.mjs","names":[],"sources":["../../src/operations/connect-channel.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Operation from '@dxos/compute/Operation';\nimport { Database } from '@dxos/echo';\n\nimport { ChannelBackend, ThreadOperation } from '#types';\n\nconst handler: Operation.WithHandler<typeof ThreadOperation.ConnectChannel> = ThreadOperation.ConnectChannel.pipe(\n Operation.withHandler(\n Effect.fnUntraced(function* ({ channel: channelRef }) {\n const channel = yield* Database.load(channelRef);\n const provider = yield* ChannelBackend.getProvider(channel);\n const connection = yield* ChannelBackend.requireMember(provider, 'connection');\n return { status: yield* connection.start(channel) };\n }),\n ),\n);\n\nexport default handler;\n"],"mappings":";;;;;AAWA,IAAM,UAAwE,gBAAgB,eAAe,KAC3G,UAAU,YACR,OAAO,WAAW,WAAW,EAAE,SAAS,cAAc;CACpD,MAAM,UAAU,OAAO,SAAS,KAAK,UAAU;CAC/C,MAAM,WAAW,OAAO,eAAe,YAAY,OAAO;CAE1D,OAAO,EAAE,QAAQ,QAAO,OADE,eAAe,cAAc,UAAU,YAAY,EAAA,CAC1C,MAAM,OAAO,EAAE;AACpD,CAAC,CACH,CACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Capability from "@dxos/app-framework/Capability";
|
|
2
2
|
import { ChannelBackend, ThreadCapabilities, ThreadOperation } from "#types";
|
|
3
|
-
import { Channel } from "@dxos/types";
|
|
4
3
|
import * as Operation from "@dxos/compute/Operation";
|
|
4
|
+
import { Channel } from "@dxos/types";
|
|
5
5
|
import * as Effect from "effect/Effect";
|
|
6
6
|
import { invariant } from "@dxos/invariant";
|
|
7
7
|
//#region src/operations/create-channel.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as Capability from "@dxos/app-framework/Capability";
|
|
2
2
|
import { ChannelBackend, ThreadCapabilities } from "#types";
|
|
3
|
-
import { Channel } from "@dxos/types";
|
|
4
3
|
import * as Operation from "@dxos/compute/Operation";
|
|
5
4
|
import { Type } from "@dxos/echo";
|
|
5
|
+
import { Channel } from "@dxos/types";
|
|
6
6
|
import * as Effect from "effect/Effect";
|
|
7
7
|
import * as SpaceOperation from "@dxos/plugin-space/SpaceOperation";
|
|
8
8
|
import * as SpaceCapabilities from "@dxos/plugin-space/SpaceCapabilities";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ChannelBackend, ThreadOperation } from "#types";
|
|
2
|
+
import * as Operation from "@dxos/compute/Operation";
|
|
3
|
+
import { Database } from "@dxos/echo";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
//#region src/operations/disconnect-channel.ts
|
|
6
|
+
var handler = ThreadOperation.DisconnectChannel.pipe(Operation.withHandler(Effect.fnUntraced(function* ({ channel: channelRef }) {
|
|
7
|
+
const channel = yield* Database.load(channelRef);
|
|
8
|
+
const provider = yield* ChannelBackend.getProvider(channel);
|
|
9
|
+
return { status: yield* (yield* ChannelBackend.requireMember(provider, "connection")).stop(channel) };
|
|
10
|
+
})));
|
|
11
|
+
//#endregion
|
|
12
|
+
export { handler as default };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=chunk-disconnect-channel.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-disconnect-channel.mjs","names":[],"sources":["../../src/operations/disconnect-channel.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Operation from '@dxos/compute/Operation';\nimport { Database } from '@dxos/echo';\n\nimport { ChannelBackend, ThreadOperation } from '#types';\n\nconst handler: Operation.WithHandler<typeof ThreadOperation.DisconnectChannel> = ThreadOperation.DisconnectChannel.pipe(\n Operation.withHandler(\n Effect.fnUntraced(function* ({ channel: channelRef }) {\n const channel = yield* Database.load(channelRef);\n const provider = yield* ChannelBackend.getProvider(channel);\n const connection = yield* ChannelBackend.requireMember(provider, 'connection');\n return { status: yield* connection.stop(channel) };\n }),\n ),\n);\n\nexport default handler;\n"],"mappings":";;;;;AAWA,IAAM,UAA2E,gBAAgB,kBAAkB,KACjH,UAAU,YACR,OAAO,WAAW,WAAW,EAAE,SAAS,cAAc;CACpD,MAAM,UAAU,OAAO,SAAS,KAAK,UAAU;CAC/C,MAAM,WAAW,OAAO,eAAe,YAAY,OAAO;CAE1D,OAAO,EAAE,QAAQ,QAAO,OADE,eAAe,cAAc,UAAU,YAAY,EAAA,CAC1C,KAAK,OAAO,EAAE;AACnD,CAAC,CACH,CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ChannelBackend, ThreadOperation } from "#types";
|
|
2
|
+
import * as Operation from "@dxos/compute/Operation";
|
|
3
|
+
import { Database } from "@dxos/echo";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
//#region src/operations/get-channel-status.ts
|
|
6
|
+
var handler = ThreadOperation.GetChannelStatus.pipe(Operation.withHandler(Effect.fnUntraced(function* ({ channel: channelRef }) {
|
|
7
|
+
const channel = yield* Database.load(channelRef);
|
|
8
|
+
const provider = yield* ChannelBackend.getProvider(channel);
|
|
9
|
+
return { status: yield* (yield* ChannelBackend.requireMember(provider, "connection")).status(channel) };
|
|
10
|
+
})));
|
|
11
|
+
//#endregion
|
|
12
|
+
export { handler as default };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=chunk-get-channel-status.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-get-channel-status.mjs","names":[],"sources":["../../src/operations/get-channel-status.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Operation from '@dxos/compute/Operation';\nimport { Database } from '@dxos/echo';\n\nimport { ChannelBackend, ThreadOperation } from '#types';\n\nconst handler: Operation.WithHandler<typeof ThreadOperation.GetChannelStatus> = ThreadOperation.GetChannelStatus.pipe(\n Operation.withHandler(\n Effect.fnUntraced(function* ({ channel: channelRef }) {\n const channel = yield* Database.load(channelRef);\n const provider = yield* ChannelBackend.getProvider(channel);\n const connection = yield* ChannelBackend.requireMember(provider, 'connection');\n return { status: yield* connection.status(channel) };\n }),\n ),\n);\n\nexport default handler;\n"],"mappings":";;;;;AAWA,IAAM,UAA0E,gBAAgB,iBAAiB,KAC/G,UAAU,YACR,OAAO,WAAW,WAAW,EAAE,SAAS,cAAc;CACpD,MAAM,UAAU,OAAO,SAAS,KAAK,UAAU;CAC/C,MAAM,WAAW,OAAO,eAAe,YAAY,OAAO;CAE1D,OAAO,EAAE,QAAQ,QAAO,OADE,eAAe,cAAc,UAAU,YAAY,EAAA,CAC1C,OAAO,OAAO,EAAE;AACrD,CAAC,CACH,CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ChannelBackend, ThreadOperation } from "#types";
|
|
2
|
+
import * as Operation from "@dxos/compute/Operation";
|
|
3
|
+
import { Database } from "@dxos/echo";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
//#region src/operations/open-direct.ts
|
|
6
|
+
var handler = ThreadOperation.OpenDirect.pipe(Operation.withHandler(Effect.fnUntraced(function* ({ channel: channelRef, person: personRef }) {
|
|
7
|
+
const channel = yield* Database.load(channelRef);
|
|
8
|
+
const person = yield* Database.load(personRef);
|
|
9
|
+
const provider = yield* ChannelBackend.getProvider(channel);
|
|
10
|
+
return yield* (yield* ChannelBackend.requireMember(provider, "openDirect"))(channel, person).pipe(Effect.map((thread) => thread === void 0 ? { reason: `The person has no ${provider.label} handle the channel can reach.` } : { thread }), Effect.catch((error) => Effect.succeed({ reason: error.message })));
|
|
11
|
+
})));
|
|
12
|
+
//#endregion
|
|
13
|
+
export { handler as default };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=chunk-open-direct.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-open-direct.mjs","names":[],"sources":["../../src/operations/open-direct.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Operation from '@dxos/compute/Operation';\nimport { Database } from '@dxos/echo';\n\nimport { ChannelBackend, ThreadOperation } from '#types';\n\nconst handler: Operation.WithHandler<typeof ThreadOperation.OpenDirect> = ThreadOperation.OpenDirect.pipe(\n Operation.withHandler(\n Effect.fnUntraced(function* ({ channel: channelRef, person: personRef }) {\n const channel = yield* Database.load(channelRef);\n const person = yield* Database.load(personRef);\n const provider = yield* ChannelBackend.getProvider(channel);\n const openDirect = yield* ChannelBackend.requireMember(provider, 'openDirect');\n // As with sending, a backend refusal is an outcome the caller relays.\n return yield* openDirect(channel, person).pipe(\n Effect.map((thread) =>\n thread === undefined\n ? { reason: `The person has no ${provider.label} handle the channel can reach.` }\n : { thread },\n ),\n Effect.catch((error) => Effect.succeed({ reason: error.message })),\n );\n }),\n ),\n);\n\nexport default handler;\n"],"mappings":";;;;;AAWA,IAAM,UAAoE,gBAAgB,WAAW,KACnG,UAAU,YACR,OAAO,WAAW,WAAW,EAAE,SAAS,YAAY,QAAQ,aAAa;CACvE,MAAM,UAAU,OAAO,SAAS,KAAK,UAAU;CAC/C,MAAM,SAAS,OAAO,SAAS,KAAK,SAAS;CAC7C,MAAM,WAAW,OAAO,eAAe,YAAY,OAAO;CAG1D,OAAO,QAAO,OAFY,eAAe,cAAc,UAAU,YAAY,EAAA,CAEpD,SAAS,MAAM,CAAC,CAAC,KACxC,OAAO,KAAK,WACV,WAAW,KAAA,IACP,EAAE,QAAQ,qBAAqB,SAAS,MAAM,gCAAgC,IAC9E,EAAE,OAAO,CACf,GACA,OAAO,OAAO,UAAU,OAAO,QAAQ,EAAE,QAAQ,MAAM,QAAQ,CAAC,CAAC,CACnE;AACF,CAAC,CACH,CACF"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as Capability from "@dxos/app-framework/Capability";
|
|
2
|
+
import { ThreadOperationHandlerSet } from "#operations";
|
|
2
3
|
import * as Effect from "effect/Effect";
|
|
3
4
|
import * as Capabilities from "@dxos/app-framework/Capabilities";
|
|
4
|
-
import { ThreadOperationHandlerSet } from "#operations";
|
|
5
5
|
//#region src/capabilities/operation-handler.ts
|
|
6
6
|
var operation_handler_default = Capability.makeModule(Effect.fnUntraced(function* () {
|
|
7
|
-
return Capability.contribute(Capabilities.OperationHandler, ThreadOperationHandlerSet);
|
|
7
|
+
return Capability.contribute(Capabilities.OperationHandler, ThreadOperationHandlerSet.handlers);
|
|
8
8
|
}));
|
|
9
9
|
//#endregion
|
|
10
10
|
export { operation_handler_default as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-operation-handler.mjs","names":[],"sources":["../../src/capabilities/operation-handler.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capabilities from '@dxos/app-framework/Capabilities';\nimport * as Capability from '@dxos/app-framework/Capability';\n\nimport { ThreadOperationHandlerSet } from '#operations';\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n return Capability.contribute(Capabilities.OperationHandler, ThreadOperationHandlerSet);\n }),\n);\n"],"mappings":";;;;;AAWA,IAAA,4BAAe,WAAW,WACxB,OAAO,WAAW,aAAa;CAC7B,OAAO,WAAW,WAAW,aAAa,kBAAkB,
|
|
1
|
+
{"version":3,"file":"chunk-operation-handler.mjs","names":[],"sources":["../../src/capabilities/operation-handler.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capabilities from '@dxos/app-framework/Capabilities';\nimport * as Capability from '@dxos/app-framework/Capability';\n\nimport { ThreadOperationHandlerSet } from '#operations';\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n return Capability.contribute(Capabilities.OperationHandler, ThreadOperationHandlerSet.handlers);\n }),\n);\n"],"mappings":";;;;;AAWA,IAAA,4BAAe,WAAW,WACxB,OAAO,WAAW,aAAa;CAC7B,OAAO,WAAW,WAAW,aAAa,kBAAkB,0BAA0B,QAAQ;AAChG,CAAC,CACH"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Capability from "@dxos/app-framework/Capability";
|
|
2
|
+
import * as Surface from "@dxos/app-framework/Surface";
|
|
3
|
+
import * as AppSurface from "@dxos/app-toolkit/AppSurface";
|
|
2
4
|
import { Channel, Thread } from "@dxos/types";
|
|
3
|
-
import { Surface } from "@dxos/app-framework/ui";
|
|
4
|
-
import { AppSurface } from "@dxos/app-toolkit/ui";
|
|
5
5
|
import * as Effect from "effect/Effect";
|
|
6
6
|
import { ChannelArticle, ThreadArticle } from "#containers";
|
|
7
7
|
import * as Capabilities from "@dxos/app-framework/Capabilities";
|