@dxos/plugin-thread 0.6.11 → 0.6.12-main.2d19bf1
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/{ThreadArticle-O64ZECMF.mjs → ThreadArticle-GBPIH47W.mjs} +3 -3
- package/dist/lib/browser/{ThreadMain-ZDCRC6RG.mjs → ThreadMain-PGF7W5EV.mjs} +3 -3
- package/dist/lib/browser/chunk-5G3KL6TC.mjs +16 -0
- package/dist/lib/browser/chunk-5G3KL6TC.mjs.map +7 -0
- package/dist/lib/browser/{chunk-GKPZHUT3.mjs → chunk-JFQZ5W2I.mjs} +2 -2
- package/dist/lib/browser/{chunk-GKPZHUT3.mjs.map → chunk-JFQZ5W2I.mjs.map} +1 -1
- package/dist/lib/browser/{chunk-P7ZE5N5M.mjs → chunk-O4YRHIZC.mjs} +13 -11
- package/dist/lib/browser/chunk-O4YRHIZC.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +360 -341
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/meta.mjs +1 -1
- package/dist/lib/browser/types.mjs +2 -2
- package/dist/lib/node/{ThreadArticle-DO56JXBU.cjs → ThreadArticle-GH5UBWFU.cjs} +7 -7
- package/dist/lib/node/{ThreadMain-XJX75GHG.cjs → ThreadMain-CO6I3DNX.cjs} +7 -7
- package/dist/lib/node/{chunk-5PZNPPQF.cjs → chunk-FDYRG7HE.cjs} +65 -63
- package/dist/lib/node/chunk-FDYRG7HE.cjs.map +7 -0
- package/dist/lib/node/{chunk-D5GOVXHS.cjs → chunk-FOZUQZF4.cjs} +6 -6
- package/dist/lib/node/{chunk-D5GOVXHS.cjs.map → chunk-FOZUQZF4.cjs.map} +1 -1
- package/dist/lib/node/{chunk-BWBONZGU.cjs → chunk-JIJ7Z6NO.cjs} +7 -22
- package/dist/lib/node/chunk-JIJ7Z6NO.cjs.map +7 -0
- package/dist/lib/node/index.cjs +433 -418
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.cjs +4 -4
- package/dist/lib/node/meta.cjs.map +1 -1
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types.cjs +3 -3
- package/dist/lib/node/types.cjs.map +1 -1
- package/dist/lib/node-esm/ThreadArticle-ZTYD52TR.mjs +19 -0
- package/dist/lib/node-esm/ThreadArticle-ZTYD52TR.mjs.map +7 -0
- package/dist/lib/node-esm/ThreadMain-LEHGOF7R.mjs +27 -0
- package/dist/lib/node-esm/ThreadMain-LEHGOF7R.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-DC5ZA6H5.mjs +18 -0
- package/dist/lib/node-esm/chunk-DC5ZA6H5.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-XOVJ65DG.mjs +413 -0
- package/dist/lib/node-esm/chunk-XOVJ65DG.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-ZXIPFXSA.mjs +21 -0
- package/dist/lib/node-esm/chunk-ZXIPFXSA.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1122 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/meta.mjs +12 -0
- package/dist/lib/node-esm/meta.mjs.map +7 -0
- package/dist/lib/node-esm/types.mjs +9 -0
- package/dist/lib/node-esm/types.mjs.map +7 -0
- package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
- package/dist/types/src/components/ChatContainer.d.ts.map +1 -1
- package/dist/types/src/components/CommentContainer.d.ts +1 -1
- package/dist/types/src/components/CommentContainer.d.ts.map +1 -1
- package/dist/types/src/components/CommentsContainer.d.ts +1 -5
- package/dist/types/src/components/CommentsContainer.d.ts.map +1 -1
- package/dist/types/src/components/MessageContainer.d.ts.map +1 -1
- package/dist/types/src/components/ThreadComplementary.d.ts +10 -0
- package/dist/types/src/components/ThreadComplementary.d.ts.map +1 -0
- package/dist/types/src/components/testing.d.ts +2 -0
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +2 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -0
- package/dist/types/src/extensions/threads.d.ts +9 -0
- package/dist/types/src/extensions/threads.d.ts.map +1 -0
- package/dist/types/src/meta.d.ts +3 -9
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +6 -1
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +40 -37
- package/src/ThreadPlugin.tsx +115 -310
- package/src/components/ChatContainer.tsx +7 -8
- package/src/components/CommentContainer.tsx +18 -19
- package/src/components/Comments.stories.tsx +2 -2
- package/src/components/CommentsContainer.tsx +18 -31
- package/src/components/MessageContainer.tsx +2 -1
- package/src/components/ThreadComplementary.tsx +113 -0
- package/src/extensions/index.ts +5 -0
- package/src/extensions/threads.ts +117 -0
- package/src/meta.ts +15 -0
- package/src/types.ts +8 -3
- package/dist/lib/browser/chunk-5IBJO53M.mjs +0 -21
- package/dist/lib/browser/chunk-5IBJO53M.mjs.map +0 -7
- package/dist/lib/browser/chunk-P7ZE5N5M.mjs.map +0 -7
- package/dist/lib/node/chunk-5PZNPPQF.cjs.map +0 -7
- package/dist/lib/node/chunk-BWBONZGU.cjs.map +0 -7
- package/dist/types/src/types.test.d.ts +0 -2
- package/dist/types/src/types.test.d.ts.map +0 -1
- package/src/meta.tsx +0 -20
- package/src/types.test.ts +0 -13
- /package/dist/lib/browser/{ThreadArticle-O64ZECMF.mjs.map → ThreadArticle-GBPIH47W.mjs.map} +0 -0
- /package/dist/lib/browser/{ThreadMain-ZDCRC6RG.mjs.map → ThreadMain-PGF7W5EV.mjs.map} +0 -0
- /package/dist/lib/node/{ThreadArticle-DO56JXBU.cjs.map → ThreadArticle-GH5UBWFU.cjs.map} +0 -0
- /package/dist/lib/node/{ThreadMain-XJX75GHG.cjs.map → ThreadMain-CO6I3DNX.cjs.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ThreadAction
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JFQZ5W2I.mjs";
|
|
4
4
|
import {
|
|
5
5
|
ChatContainer,
|
|
6
6
|
ChatHeading,
|
|
@@ -10,34 +10,27 @@ import {
|
|
|
10
10
|
useAnalyticsCallback,
|
|
11
11
|
useOnEditAnalytics,
|
|
12
12
|
useStatus
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-O4YRHIZC.mjs";
|
|
14
14
|
import {
|
|
15
15
|
THREAD_ITEM,
|
|
16
16
|
THREAD_PLUGIN,
|
|
17
17
|
meta_default
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-5G3KL6TC.mjs";
|
|
19
19
|
|
|
20
20
|
// packages/plugins/plugin-thread/src/ThreadPlugin.tsx
|
|
21
|
-
import
|
|
22
|
-
import {
|
|
23
|
-
import React5 from "react";
|
|
24
|
-
import { LayoutAction, NavigationAction, parseIntentPlugin, parseNavigationPlugin, resolvePlugin, parseGraphPlugin, SLUG_PATH_SEPARATOR, SLUG_COLLECTION_INDICATOR, isLayoutParts, parseMetadataResolverPlugin, useResolvePlugins } from "@dxos/app-framework";
|
|
21
|
+
import React6 from "react";
|
|
22
|
+
import { NavigationAction, parseIntentPlugin, parseNavigationPlugin, resolvePlugin, isLayoutParts, parseMetadataResolverPlugin } from "@dxos/app-framework";
|
|
25
23
|
import { getTypename } from "@dxos/echo-schema";
|
|
26
24
|
import { create as create2 } from "@dxos/echo-schema";
|
|
27
25
|
import { LocalStorageStore } from "@dxos/local-storage";
|
|
28
|
-
import {
|
|
26
|
+
import { log } from "@dxos/log";
|
|
29
27
|
import { parseClientPlugin } from "@dxos/plugin-client";
|
|
30
|
-
import { createExtension, isActionGroup } from "@dxos/plugin-graph";
|
|
31
|
-
import { DocumentType } from "@dxos/plugin-markdown/types";
|
|
28
|
+
import { createExtension, isActionGroup, toSignal } from "@dxos/plugin-graph";
|
|
32
29
|
import { ObservabilityAction } from "@dxos/plugin-observability/meta";
|
|
33
30
|
import { SpaceAction } from "@dxos/plugin-space";
|
|
34
|
-
import { ThreadType, MessageType as MessageType2, ChannelType } from "@dxos/plugin-space/types";
|
|
35
|
-
import { getSpace as
|
|
36
|
-
import { ScrollArea } from "@dxos/react-ui";
|
|
37
|
-
import { createAttendableAttributes } from "@dxos/react-ui-attention";
|
|
38
|
-
import { comments, createExternalCommentSync, listener as listener2 } from "@dxos/react-ui-editor";
|
|
31
|
+
import { ThreadType as ThreadType2, MessageType as MessageType2, ChannelType } from "@dxos/plugin-space/types";
|
|
32
|
+
import { getSpace as getSpace3, fullyQualifiedId as fullyQualifiedId5, loadObjectReferences } from "@dxos/react-client/echo";
|
|
39
33
|
import { translations as threadTranslations } from "@dxos/react-ui-thread";
|
|
40
|
-
import { nonNullable as nonNullable2 } from "@dxos/util";
|
|
41
34
|
|
|
42
35
|
// packages/plugins/plugin-thread/src/components/index.ts
|
|
43
36
|
import React4 from "react";
|
|
@@ -58,10 +51,10 @@ var ThreadSettings = ({ settings }) => {
|
|
|
58
51
|
|
|
59
52
|
// packages/plugins/plugin-thread/src/components/CommentContainer.tsx
|
|
60
53
|
import { CheckCircle, X } from "@phosphor-icons/react";
|
|
61
|
-
import React2, { useCallback,
|
|
54
|
+
import React2, { useCallback, useMemo, useRef, useState } from "react";
|
|
62
55
|
import { create } from "@dxos/echo-schema";
|
|
63
56
|
import { MessageType } from "@dxos/plugin-space/types";
|
|
64
|
-
import { getSpace, useMembers } from "@dxos/react-client/echo";
|
|
57
|
+
import { fullyQualifiedId, getSpace, useMembers } from "@dxos/react-client/echo";
|
|
65
58
|
import { useIdentity } from "@dxos/react-client/halo";
|
|
66
59
|
import { Button, Tag, Tooltip, useThemeContext, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
67
60
|
import { createBasicExtensions, createThemeExtensions, listener } from "@dxos/react-ui-editor";
|
|
@@ -114,16 +107,15 @@ var DeleteThreadButton = ({ onDelete }) => {
|
|
|
114
107
|
classNames: "z-[21]"
|
|
115
108
|
}, label, /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
|
|
116
109
|
};
|
|
117
|
-
var CommentContainer = ({ thread, detached, context, current,
|
|
110
|
+
var CommentContainer = ({ thread, detached, context, current, onAttend, onThreadDelete, onMessageDelete, onResolve, onComment }) => {
|
|
118
111
|
const identity = useIdentity();
|
|
119
112
|
const space = getSpace(thread);
|
|
120
113
|
const members = useMembers(space?.key);
|
|
121
|
-
const activity = useStatus(space, thread
|
|
114
|
+
const activity = useStatus(space, fullyQualifiedId(thread));
|
|
122
115
|
const { t } = useTranslation2(THREAD_PLUGIN);
|
|
123
116
|
const threadScrollRef = useRef(null);
|
|
124
|
-
const [autoFocus, setAutoFocus] = useState(!!autoFocusTextbox);
|
|
125
117
|
const { themeMode } = useThemeContext();
|
|
126
|
-
const textboxMetadata = getMessageMetadata(thread
|
|
118
|
+
const textboxMetadata = getMessageMetadata(fullyQualifiedId(thread), identity);
|
|
127
119
|
const [_count, _setCount] = useState(0);
|
|
128
120
|
const rerenderEditor = () => _setCount((count) => count + 1);
|
|
129
121
|
const messageRef = useRef("");
|
|
@@ -141,11 +133,6 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
|
|
|
141
133
|
], [
|
|
142
134
|
_count
|
|
143
135
|
]);
|
|
144
|
-
useEffect(() => {
|
|
145
|
-
setAutoFocus(!!autoFocusTextbox);
|
|
146
|
-
}, [
|
|
147
|
-
autoFocusTextbox
|
|
148
|
-
]);
|
|
149
136
|
const scrollToEnd = (behavior) => setTimeout(() => threadScrollRef.current?.scrollIntoView({
|
|
150
137
|
behavior,
|
|
151
138
|
block: "end"
|
|
@@ -164,7 +151,6 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
|
|
|
164
151
|
}));
|
|
165
152
|
onComment?.(thread);
|
|
166
153
|
messageRef.current = "";
|
|
167
|
-
setAutoFocus(true);
|
|
168
154
|
scrollToEnd("instant");
|
|
169
155
|
rerenderEditor();
|
|
170
156
|
return true;
|
|
@@ -172,12 +158,11 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
|
|
|
172
158
|
thread,
|
|
173
159
|
identity
|
|
174
160
|
]);
|
|
175
|
-
const handleDeleteMessage = (id) => onMessageDelete?.(id);
|
|
176
161
|
return /* @__PURE__ */ React2.createElement(Thread, {
|
|
177
162
|
onClickCapture: onAttend,
|
|
178
163
|
onFocusCapture: onAttend,
|
|
179
164
|
current,
|
|
180
|
-
id: thread
|
|
165
|
+
id: fullyQualifiedId(thread)
|
|
181
166
|
}, /* @__PURE__ */ React2.createElement("div", {
|
|
182
167
|
role: "none",
|
|
183
168
|
className: mx("col-span-2 grid grid-cols-[var(--rail-size)_1fr_min-content]", hoverableControls, hoverableFocusedWithinControls)
|
|
@@ -201,10 +186,9 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
|
|
|
201
186
|
key: message.id,
|
|
202
187
|
message,
|
|
203
188
|
members,
|
|
204
|
-
onDelete:
|
|
189
|
+
onDelete: (id) => onMessageDelete?.(id)
|
|
205
190
|
})), /* @__PURE__ */ React2.createElement(MessageTextbox, {
|
|
206
191
|
extensions,
|
|
207
|
-
autoFocus,
|
|
208
192
|
onSend: handleCreate,
|
|
209
193
|
...textboxMetadata
|
|
210
194
|
}), /* @__PURE__ */ React2.createElement(ThreadFooter, {
|
|
@@ -217,26 +201,15 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
|
|
|
217
201
|
};
|
|
218
202
|
|
|
219
203
|
// packages/plugins/plugin-thread/src/components/CommentsContainer.tsx
|
|
220
|
-
import { ChatText
|
|
221
|
-
import React3, { useEffect
|
|
204
|
+
import { ChatText } from "@phosphor-icons/react";
|
|
205
|
+
import React3, { useEffect } from "react";
|
|
206
|
+
import { fullyQualifiedId as fullyQualifiedId2 } from "@dxos/react-client/echo";
|
|
222
207
|
import { useTranslation as useTranslation3, Trans } from "@dxos/react-ui";
|
|
223
|
-
import { PlankHeading, plankHeadingIconProps } from "@dxos/react-ui-deck";
|
|
224
208
|
import { descriptionText, mx as mx2 } from "@dxos/react-ui-theme";
|
|
225
|
-
var
|
|
209
|
+
var CommentsContainer = ({ threads: threads2, detached = [], currentId, showResolvedThreads, onThreadAttend, onThreadDelete, onMessageDelete, onThreadToggleResolved, ...props }) => {
|
|
226
210
|
const { t } = useTranslation3(THREAD_PLUGIN);
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
className: "flex items-center"
|
|
230
|
-
}, /* @__PURE__ */ React3.createElement(PlankHeading.Button, {
|
|
231
|
-
attendableId
|
|
232
|
-
}, /* @__PURE__ */ React3.createElement(Quotes, plankHeadingIconProps)), /* @__PURE__ */ React3.createElement(PlankHeading.Label, {
|
|
233
|
-
attendableId
|
|
234
|
-
}, t("comments heading")));
|
|
235
|
-
};
|
|
236
|
-
var CommentsContainer = ({ threads, detached = [], currentId, autoFocusCurrentTextbox, showResolvedThreads, onThreadAttend, onThreadDelete, onMessageDelete, onThreadToggleResolved, ...props }) => {
|
|
237
|
-
const { t } = useTranslation3(THREAD_PLUGIN);
|
|
238
|
-
const filteredThreads = showResolvedThreads ? threads : threads.filter((thread) => !(thread?.status === "resolved"));
|
|
239
|
-
useEffect2(() => {
|
|
211
|
+
const filteredThreads = showResolvedThreads ? threads2 : threads2.filter((thread) => !(thread?.status === "resolved"));
|
|
212
|
+
useEffect(() => {
|
|
240
213
|
if (currentId) {
|
|
241
214
|
document.getElementById(currentId)?.scrollIntoView({
|
|
242
215
|
behavior: "smooth",
|
|
@@ -246,26 +219,28 @@ var CommentsContainer = ({ threads, detached = [], currentId, autoFocusCurrentTe
|
|
|
246
219
|
}, [
|
|
247
220
|
currentId
|
|
248
221
|
]);
|
|
249
|
-
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, filteredThreads.length > 0 ? filteredThreads.map((thread) =>
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
onThreadDelete
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
onMessageDelete
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
222
|
+
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, filteredThreads.length > 0 ? filteredThreads.map((thread) => {
|
|
223
|
+
const threadId = fullyQualifiedId2(thread);
|
|
224
|
+
return /* @__PURE__ */ React3.createElement(CommentContainer, {
|
|
225
|
+
key: threadId,
|
|
226
|
+
thread,
|
|
227
|
+
current: currentId === threadId,
|
|
228
|
+
detached: detached.includes(threadId),
|
|
229
|
+
...onThreadAttend && {
|
|
230
|
+
onAttend: () => onThreadAttend(thread)
|
|
231
|
+
},
|
|
232
|
+
...onThreadDelete && {
|
|
233
|
+
onThreadDelete: () => onThreadDelete(thread)
|
|
234
|
+
},
|
|
235
|
+
...onMessageDelete && {
|
|
236
|
+
onMessageDelete: (messageId) => onMessageDelete(thread, messageId)
|
|
237
|
+
},
|
|
238
|
+
...onThreadToggleResolved && {
|
|
239
|
+
onResolve: () => onThreadToggleResolved(thread)
|
|
240
|
+
},
|
|
241
|
+
...props
|
|
242
|
+
});
|
|
243
|
+
}) : /* @__PURE__ */ React3.createElement("div", {
|
|
269
244
|
role: "alert",
|
|
270
245
|
className: mx2(descriptionText, "place-self-center border border-dashed border-neutral-400/50 rounded-lg text-center p-4 m-4")
|
|
271
246
|
}, /* @__PURE__ */ React3.createElement("h2", {
|
|
@@ -282,8 +257,208 @@ var CommentsContainer = ({ threads, detached = [], currentId, autoFocusCurrentTe
|
|
|
282
257
|
};
|
|
283
258
|
|
|
284
259
|
// packages/plugins/plugin-thread/src/components/index.ts
|
|
285
|
-
var ThreadMain = React4.lazy(() => import("./ThreadMain-
|
|
286
|
-
var ThreadArticle = React4.lazy(() => import("./ThreadArticle-
|
|
260
|
+
var ThreadMain = React4.lazy(() => import("./ThreadMain-PGF7W5EV.mjs"));
|
|
261
|
+
var ThreadArticle = React4.lazy(() => import("./ThreadArticle-GBPIH47W.mjs"));
|
|
262
|
+
|
|
263
|
+
// packages/plugins/plugin-thread/src/components/ThreadComplementary.tsx
|
|
264
|
+
import React5, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
|
|
265
|
+
import { LayoutAction, useIntentDispatcher, useResolvePlugins } from "@dxos/app-framework";
|
|
266
|
+
import { fullyQualifiedId as fullyQualifiedId3 } from "@dxos/react-client/echo";
|
|
267
|
+
import { ScrollArea } from "@dxos/react-ui";
|
|
268
|
+
import { useAttended } from "@dxos/react-ui-attention";
|
|
269
|
+
import { nonNullable as nonNullable2 } from "@dxos/util";
|
|
270
|
+
var providesThreadsConfig = (plugin) => "thread" in plugin.provides ? plugin : void 0;
|
|
271
|
+
var ThreadComplementary = ({ role, subject, drafts, current, showResolvedThreads }) => {
|
|
272
|
+
const dispatch = useIntentDispatcher();
|
|
273
|
+
const threadsIntegrators = useResolvePlugins(providesThreadsConfig);
|
|
274
|
+
const threadProvides = useMemo2(() => threadsIntegrators.map((p) => p.provides.thread), [
|
|
275
|
+
threadsIntegrators
|
|
276
|
+
]);
|
|
277
|
+
const createSort = useMemo2(() => threadProvides.find((p) => p.predicate(subject))?.createSort, [
|
|
278
|
+
threadProvides,
|
|
279
|
+
subject
|
|
280
|
+
]);
|
|
281
|
+
const sort = useMemo2(() => createSort?.(subject), [
|
|
282
|
+
createSort,
|
|
283
|
+
subject
|
|
284
|
+
]);
|
|
285
|
+
const threads2 = useMemo2(() => {
|
|
286
|
+
return subject.threads.concat(drafts ?? []).filter(nonNullable2);
|
|
287
|
+
}, [
|
|
288
|
+
JSON.stringify(subject.threads),
|
|
289
|
+
JSON.stringify(drafts)
|
|
290
|
+
]);
|
|
291
|
+
const detachedIds = useMemo2(() => {
|
|
292
|
+
return threads2.filter(({ anchor }) => !anchor).map((thread) => fullyQualifiedId3(thread));
|
|
293
|
+
}, [
|
|
294
|
+
threads2
|
|
295
|
+
]);
|
|
296
|
+
useEffect2(() => {
|
|
297
|
+
if (!sort) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
threads2.sort((a, b) => sort(a?.anchor, b?.anchor));
|
|
301
|
+
}, [
|
|
302
|
+
sort,
|
|
303
|
+
threads2
|
|
304
|
+
]);
|
|
305
|
+
const attended = useAttended();
|
|
306
|
+
const qualifiedSubjectId = fullyQualifiedId3(subject);
|
|
307
|
+
return /* @__PURE__ */ React5.createElement("div", {
|
|
308
|
+
role: "none",
|
|
309
|
+
className: "contents"
|
|
310
|
+
}, /* @__PURE__ */ React5.createElement(ScrollArea.Root, {
|
|
311
|
+
classNames: "row-span-2"
|
|
312
|
+
}, /* @__PURE__ */ React5.createElement(ScrollArea.Viewport, null, /* @__PURE__ */ React5.createElement(CommentsContainer, {
|
|
313
|
+
threads: threads2,
|
|
314
|
+
detached: detachedIds,
|
|
315
|
+
currentId: attended.includes(qualifiedSubjectId) ? current : void 0,
|
|
316
|
+
showResolvedThreads,
|
|
317
|
+
onThreadAttend: (thread) => {
|
|
318
|
+
const threadId = fullyQualifiedId3(thread);
|
|
319
|
+
if (current !== threadId) {
|
|
320
|
+
current = threadId;
|
|
321
|
+
void dispatch?.([
|
|
322
|
+
{
|
|
323
|
+
action: LayoutAction.SCROLL_INTO_VIEW,
|
|
324
|
+
data: {
|
|
325
|
+
id: fullyQualifiedId3(subject),
|
|
326
|
+
thread: threadId,
|
|
327
|
+
cursor: thread.anchor
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
]);
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
onThreadDelete: (thread) => {
|
|
334
|
+
return dispatch({
|
|
335
|
+
plugin: THREAD_PLUGIN,
|
|
336
|
+
action: ThreadAction.DELETE,
|
|
337
|
+
data: {
|
|
338
|
+
subject,
|
|
339
|
+
thread
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
},
|
|
343
|
+
onMessageDelete: (thread, messageId) => dispatch({
|
|
344
|
+
plugin: THREAD_PLUGIN,
|
|
345
|
+
action: ThreadAction.DELETE_MESSAGE,
|
|
346
|
+
data: {
|
|
347
|
+
subject,
|
|
348
|
+
thread,
|
|
349
|
+
messageId
|
|
350
|
+
}
|
|
351
|
+
}),
|
|
352
|
+
onThreadToggleResolved: (thread) => dispatch({
|
|
353
|
+
plugin: THREAD_PLUGIN,
|
|
354
|
+
action: ThreadAction.TOGGLE_RESOLVED,
|
|
355
|
+
data: {
|
|
356
|
+
thread
|
|
357
|
+
}
|
|
358
|
+
}),
|
|
359
|
+
onComment: (thread) => {
|
|
360
|
+
void dispatch({
|
|
361
|
+
action: ThreadAction.ON_MESSAGE_ADD,
|
|
362
|
+
data: {
|
|
363
|
+
thread,
|
|
364
|
+
subject
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}), /* @__PURE__ */ React5.createElement("div", {
|
|
369
|
+
role: "none",
|
|
370
|
+
className: "bs-10"
|
|
371
|
+
}), /* @__PURE__ */ React5.createElement(ScrollArea.Scrollbar, null, /* @__PURE__ */ React5.createElement(ScrollArea.Thumb, null)))));
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
// packages/plugins/plugin-thread/src/extensions/threads.ts
|
|
375
|
+
import { EditorView } from "@codemirror/view";
|
|
376
|
+
import { computed, effect } from "@preact/signals-core";
|
|
377
|
+
import { ThreadType } from "@dxos/plugin-space/types";
|
|
378
|
+
import { getSpace as getSpace2, getTextInRange, createDocAccessor, fullyQualifiedId as fullyQualifiedId4 } from "@dxos/react-client/echo";
|
|
379
|
+
import { comments, createExternalCommentSync } from "@dxos/react-ui-editor";
|
|
380
|
+
import { nonNullable as nonNullable3 } from "@dxos/util";
|
|
381
|
+
var getName = (doc, anchor) => {
|
|
382
|
+
if (doc.content) {
|
|
383
|
+
const [start, end] = anchor.split(":");
|
|
384
|
+
return getTextInRange(createDocAccessor(doc.content, [
|
|
385
|
+
"content"
|
|
386
|
+
]), start, end);
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
var threads = (state, doc, dispatch) => {
|
|
390
|
+
const space = doc && getSpace2(doc);
|
|
391
|
+
if (!doc || !space || !dispatch) {
|
|
392
|
+
return [
|
|
393
|
+
comments()
|
|
394
|
+
];
|
|
395
|
+
}
|
|
396
|
+
const threads2 = computed(() => [
|
|
397
|
+
...doc.threads.filter(nonNullable3),
|
|
398
|
+
...state.drafts[fullyQualifiedId4(doc)] ?? []
|
|
399
|
+
].filter((thread) => !(thread?.status === "resolved")));
|
|
400
|
+
return [
|
|
401
|
+
EditorView.updateListener.of((update) => {
|
|
402
|
+
if (update.docChanged) {
|
|
403
|
+
doc.threads.forEach((thread) => {
|
|
404
|
+
if (thread?.anchor) {
|
|
405
|
+
const name = getName(doc, thread.anchor);
|
|
406
|
+
if (name && name !== thread.name) {
|
|
407
|
+
thread.name = name;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
}),
|
|
413
|
+
createExternalCommentSync(fullyQualifiedId4(doc), (sink) => effect(() => sink()), () => threads2.value.filter((thread) => thread?.anchor).map((thread) => ({
|
|
414
|
+
id: fullyQualifiedId4(thread),
|
|
415
|
+
cursor: thread.anchor
|
|
416
|
+
}))),
|
|
417
|
+
comments({
|
|
418
|
+
id: fullyQualifiedId4(doc),
|
|
419
|
+
onCreate: ({ cursor }) => {
|
|
420
|
+
const name = getName(doc, cursor);
|
|
421
|
+
void dispatch({
|
|
422
|
+
action: ThreadAction.CREATE,
|
|
423
|
+
data: {
|
|
424
|
+
cursor,
|
|
425
|
+
name,
|
|
426
|
+
subject: doc
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
},
|
|
430
|
+
onDelete: ({ id }) => {
|
|
431
|
+
const draft = state.drafts[fullyQualifiedId4(doc)];
|
|
432
|
+
if (draft) {
|
|
433
|
+
const index = draft.findIndex((thread2) => fullyQualifiedId4(thread2) === id);
|
|
434
|
+
if (index !== -1) {
|
|
435
|
+
draft.splice(index, 1);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
const thread = doc.threads.find((thread2) => thread2?.id === id);
|
|
439
|
+
if (thread) {
|
|
440
|
+
thread.anchor = void 0;
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
onUpdate: ({ id, cursor }) => {
|
|
444
|
+
const thread = state.drafts[fullyQualifiedId4(doc)]?.find((thread2) => fullyQualifiedId4(thread2) === id) ?? doc.threads.find((thread2) => thread2?.id === id);
|
|
445
|
+
if (thread instanceof ThreadType && thread.anchor) {
|
|
446
|
+
thread.name = getName(doc, thread.anchor);
|
|
447
|
+
thread.anchor = cursor;
|
|
448
|
+
}
|
|
449
|
+
},
|
|
450
|
+
onSelect: ({ selection: { current, closest } }) => {
|
|
451
|
+
void dispatch({
|
|
452
|
+
action: ThreadAction.SELECT,
|
|
453
|
+
data: {
|
|
454
|
+
current: current ?? closest,
|
|
455
|
+
skipOpen: true
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
})
|
|
460
|
+
];
|
|
461
|
+
};
|
|
287
462
|
|
|
288
463
|
// packages/plugins/plugin-thread/src/translations.ts
|
|
289
464
|
var translations_default = [
|
|
@@ -322,14 +497,14 @@ var translations_default = [
|
|
|
322
497
|
];
|
|
323
498
|
|
|
324
499
|
// packages/plugins/plugin-thread/src/ThreadPlugin.tsx
|
|
500
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/plugin-thread/src/ThreadPlugin.tsx";
|
|
325
501
|
var initialViewState = {
|
|
326
502
|
showResolvedThreads: false
|
|
327
503
|
};
|
|
328
|
-
var providesThreadsConfig = (plugin) => "thread" in plugin.provides ? plugin : void 0;
|
|
329
504
|
var ThreadPlugin = () => {
|
|
330
505
|
const settings = new LocalStorageStore(THREAD_PLUGIN);
|
|
331
506
|
const state = create2({
|
|
332
|
-
|
|
507
|
+
drafts: {}
|
|
333
508
|
});
|
|
334
509
|
const viewStore = create2({});
|
|
335
510
|
const getViewState = (subjectId) => {
|
|
@@ -340,10 +515,8 @@ var ThreadPlugin = () => {
|
|
|
340
515
|
}
|
|
341
516
|
return viewStore[subjectId];
|
|
342
517
|
};
|
|
343
|
-
let attentionPlugin;
|
|
344
518
|
let navigationPlugin;
|
|
345
519
|
let intentPlugin;
|
|
346
|
-
let dispatch;
|
|
347
520
|
const unsubscribeCallbacks = [];
|
|
348
521
|
return {
|
|
349
522
|
meta: meta_default,
|
|
@@ -354,36 +527,8 @@ var ThreadPlugin = () => {
|
|
|
354
527
|
allowUndefined: true
|
|
355
528
|
})
|
|
356
529
|
});
|
|
357
|
-
attentionPlugin = resolvePlugin(plugins, parseAttentionPlugin);
|
|
358
530
|
navigationPlugin = resolvePlugin(plugins, parseNavigationPlugin);
|
|
359
531
|
intentPlugin = resolvePlugin(plugins, parseIntentPlugin);
|
|
360
|
-
dispatch = intentPlugin?.provides.intent.dispatch;
|
|
361
|
-
const graphPlugin = resolvePlugin(plugins, parseGraphPlugin);
|
|
362
|
-
const client = resolvePlugin(plugins, parseClientPlugin)?.provides.client;
|
|
363
|
-
if (!client) {
|
|
364
|
-
return;
|
|
365
|
-
}
|
|
366
|
-
const channelsQuery = client.spaces.query(Filter.schema(ChannelType));
|
|
367
|
-
const queryUnsubscribe = channelsQuery.subscribe();
|
|
368
|
-
const unsubscribe = effect(() => {
|
|
369
|
-
const attention = attentionPlugin?.provides.attention;
|
|
370
|
-
if (!attention?.attended) {
|
|
371
|
-
return;
|
|
372
|
-
}
|
|
373
|
-
const firstAttendedNodeWithComments = Array.from(attention.attended).map((id) => graphPlugin?.provides.graph.findNode(id)).find((node) => node?.data instanceof DocumentType && (node.data.threads?.length ?? 0) > 0);
|
|
374
|
-
if (firstAttendedNodeWithComments) {
|
|
375
|
-
void intentPlugin?.provides.intent.dispatch({
|
|
376
|
-
action: NavigationAction.OPEN,
|
|
377
|
-
data: {
|
|
378
|
-
activeParts: {
|
|
379
|
-
complementary: `${firstAttendedNodeWithComments.id}${SLUG_PATH_SEPARATOR}comments`
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
});
|
|
385
|
-
unsubscribeCallbacks.push(queryUnsubscribe);
|
|
386
|
-
unsubscribeCallbacks.push(unsubscribe);
|
|
387
532
|
},
|
|
388
533
|
unload: async () => {
|
|
389
534
|
unsubscribeCallbacks.forEach((unsubscribe) => unsubscribe());
|
|
@@ -399,12 +544,11 @@ var ThreadPlugin = () => {
|
|
|
399
544
|
ns: THREAD_PLUGIN
|
|
400
545
|
}
|
|
401
546
|
],
|
|
402
|
-
icon:
|
|
403
|
-
iconSymbol: "ph--chat--regular",
|
|
547
|
+
icon: "ph--chat--regular",
|
|
404
548
|
// TODO(wittjosiah): Move out of metadata.
|
|
405
549
|
loadReferences: (channel) => loadObjectReferences(channel, (channel2) => channel2.threads)
|
|
406
550
|
},
|
|
407
|
-
[
|
|
551
|
+
[ThreadType2.typename]: {
|
|
408
552
|
// TODO(wittjosiah): Move out of metadata.
|
|
409
553
|
loadReferences: (thread) => loadObjectReferences(thread, (thread2) => thread2.messages)
|
|
410
554
|
},
|
|
@@ -440,16 +584,16 @@ var ThreadPlugin = () => {
|
|
|
440
584
|
echo: {
|
|
441
585
|
schema: [
|
|
442
586
|
ChannelType,
|
|
443
|
-
|
|
587
|
+
ThreadType2,
|
|
444
588
|
MessageType2
|
|
445
589
|
]
|
|
446
590
|
},
|
|
447
591
|
graph: {
|
|
448
592
|
builder: (plugins) => {
|
|
449
593
|
const client = resolvePlugin(plugins, parseClientPlugin)?.provides.client;
|
|
450
|
-
const
|
|
594
|
+
const dispatch = resolvePlugin(plugins, parseIntentPlugin)?.provides.intent.dispatch;
|
|
451
595
|
const metadataResolver = resolvePlugin(plugins, parseMetadataResolverPlugin)?.provides.metadata.resolver;
|
|
452
|
-
if (!client || !
|
|
596
|
+
if (!client || !dispatch || !metadataResolver) {
|
|
453
597
|
return [];
|
|
454
598
|
}
|
|
455
599
|
return [
|
|
@@ -459,29 +603,36 @@ var ThreadPlugin = () => {
|
|
|
459
603
|
if (!id.endsWith("~comments")) {
|
|
460
604
|
return;
|
|
461
605
|
}
|
|
462
|
-
const
|
|
463
|
-
const [spaceId, objectId] =
|
|
606
|
+
const subjectId = id.split("~").at(0);
|
|
607
|
+
const [spaceId, objectId] = subjectId?.split(":") ?? [];
|
|
464
608
|
const space = client.spaces.get().find((space2) => space2.id === spaceId);
|
|
465
|
-
const
|
|
466
|
-
|
|
609
|
+
const object = toSignal((onChange) => {
|
|
610
|
+
const timeout = setTimeout(async () => {
|
|
611
|
+
await space?.db.loadObjectById(objectId);
|
|
612
|
+
onChange();
|
|
613
|
+
});
|
|
614
|
+
return () => clearTimeout(timeout);
|
|
615
|
+
}, () => space?.db.getObjectById(objectId), subjectId);
|
|
616
|
+
if (!object || !subjectId) {
|
|
467
617
|
return;
|
|
468
618
|
}
|
|
469
|
-
const
|
|
470
|
-
const label =
|
|
619
|
+
const meta = metadataResolver(getTypename(object) ?? "");
|
|
620
|
+
const label = meta.label?.(object) || object.name || meta.placeholder || [
|
|
471
621
|
"unnamed object threads label",
|
|
472
622
|
{
|
|
473
623
|
ns: THREAD_PLUGIN
|
|
474
624
|
}
|
|
475
625
|
];
|
|
476
|
-
const viewState = getViewState(
|
|
626
|
+
const viewState = getViewState(subjectId);
|
|
477
627
|
return {
|
|
478
628
|
id,
|
|
479
629
|
type: "orphan-comments-for-subject",
|
|
480
|
-
data:
|
|
630
|
+
data: null,
|
|
481
631
|
properties: {
|
|
482
|
-
icon:
|
|
632
|
+
icon: "ph--chat-text--regular",
|
|
483
633
|
label,
|
|
484
|
-
showResolvedThreads: viewState.showResolvedThreads
|
|
634
|
+
showResolvedThreads: viewState.showResolvedThreads,
|
|
635
|
+
object
|
|
485
636
|
}
|
|
486
637
|
};
|
|
487
638
|
},
|
|
@@ -495,7 +646,7 @@ var ThreadPlugin = () => {
|
|
|
495
646
|
const toggle = () => {
|
|
496
647
|
const newToggleState = !viewState.showResolvedThreads;
|
|
497
648
|
viewState.showResolvedThreads = newToggleState;
|
|
498
|
-
void
|
|
649
|
+
void dispatch({
|
|
499
650
|
action: ObservabilityAction.SEND_EVENT,
|
|
500
651
|
data: {
|
|
501
652
|
name: "threads.toggle-show-resolved",
|
|
@@ -520,7 +671,8 @@ var ThreadPlugin = () => {
|
|
|
520
671
|
],
|
|
521
672
|
menuItemType: "toggle",
|
|
522
673
|
isChecked: viewState.showResolvedThreads,
|
|
523
|
-
testId: "threadPlugin.toggleShowResolved"
|
|
674
|
+
testId: "threadPlugin.toggleShowResolved",
|
|
675
|
+
icon: viewState.showResolvedThreads ? "ph--eye-slash--regular" : "ph--eye--regular"
|
|
524
676
|
}
|
|
525
677
|
}
|
|
526
678
|
];
|
|
@@ -542,7 +694,7 @@ var ThreadPlugin = () => {
|
|
|
542
694
|
{
|
|
543
695
|
id: `${THREAD_PLUGIN}/create/${node.id}`,
|
|
544
696
|
data: async () => {
|
|
545
|
-
await
|
|
697
|
+
await dispatch([
|
|
546
698
|
{
|
|
547
699
|
plugin: THREAD_PLUGIN,
|
|
548
700
|
action: ThreadAction.CREATE
|
|
@@ -565,8 +717,7 @@ var ThreadPlugin = () => {
|
|
|
565
717
|
ns: THREAD_PLUGIN
|
|
566
718
|
}
|
|
567
719
|
],
|
|
568
|
-
icon:
|
|
569
|
-
iconSymbol: "ph--chat--regular",
|
|
720
|
+
icon: "ph--chat--regular",
|
|
570
721
|
testId: "threadPlugin.createObject"
|
|
571
722
|
}
|
|
572
723
|
}
|
|
@@ -580,20 +731,17 @@ var ThreadPlugin = () => {
|
|
|
580
731
|
component: ({ data, role }) => {
|
|
581
732
|
switch (role) {
|
|
582
733
|
case "main": {
|
|
583
|
-
return data.active instanceof ChannelType && data.active.threads[0] ? /* @__PURE__ */
|
|
734
|
+
return data.active instanceof ChannelType && data.active.threads[0] ? /* @__PURE__ */ React6.createElement(ThreadMain, {
|
|
584
735
|
thread: data.active.threads[0]
|
|
585
736
|
}) : null;
|
|
586
737
|
}
|
|
587
738
|
case "settings": {
|
|
588
|
-
return data.plugin === meta_default.id ? /* @__PURE__ */
|
|
739
|
+
return data.plugin === meta_default.id ? /* @__PURE__ */ React6.createElement(ThreadSettings, {
|
|
589
740
|
settings: settings.values
|
|
590
741
|
}) : null;
|
|
591
742
|
}
|
|
592
|
-
case "article":
|
|
593
|
-
case "complementary": {
|
|
743
|
+
case "article": {
|
|
594
744
|
const location = navigationPlugin?.provides.location;
|
|
595
|
-
const threadsIntegrators = useResolvePlugins(providesThreadsConfig);
|
|
596
|
-
const threadProvides = threadsIntegrators.map((p) => p.provides.thread);
|
|
597
745
|
if (data.object instanceof ChannelType && data.object.threads[0]) {
|
|
598
746
|
const channel = data.object;
|
|
599
747
|
if (isLayoutParts(location?.active) && location.active.main) {
|
|
@@ -601,103 +749,38 @@ var ThreadPlugin = () => {
|
|
|
601
749
|
const currentPosition = layoutEntries.findIndex((entry) => channel.id === entry.id);
|
|
602
750
|
if (currentPosition > 0) {
|
|
603
751
|
const objectToTheLeft = layoutEntries[currentPosition - 1];
|
|
604
|
-
const context =
|
|
605
|
-
return /* @__PURE__ */
|
|
752
|
+
const context = getSpace3(data.object)?.db.getObjectById(objectToTheLeft.id);
|
|
753
|
+
return /* @__PURE__ */ React6.createElement(ThreadArticle, {
|
|
606
754
|
thread: data.object.threads[0],
|
|
607
755
|
context
|
|
608
756
|
});
|
|
609
757
|
}
|
|
610
758
|
}
|
|
611
|
-
return /* @__PURE__ */
|
|
759
|
+
return /* @__PURE__ */ React6.createElement(ThreadArticle, {
|
|
612
760
|
thread: data.object.threads[0]
|
|
613
761
|
});
|
|
614
762
|
}
|
|
615
|
-
if (data.subject instanceof
|
|
616
|
-
return /* @__PURE__ */
|
|
763
|
+
if (data.subject instanceof ThreadType2) {
|
|
764
|
+
return /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(ChatHeading, {
|
|
617
765
|
attendableId: data.subject.id
|
|
618
|
-
}), /* @__PURE__ */
|
|
766
|
+
}), /* @__PURE__ */ React6.createElement(ChatContainer, {
|
|
619
767
|
thread: data.subject
|
|
620
768
|
}));
|
|
621
769
|
}
|
|
770
|
+
break;
|
|
771
|
+
}
|
|
772
|
+
case "complementary--comments": {
|
|
622
773
|
if (data.subject && typeof data.subject === "object" && "threads" in data.subject && Array.isArray(data.subject.threads)) {
|
|
623
|
-
const
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
const attention = attentionPlugin?.provides.attention?.attended ?? /* @__PURE__ */ new Set([
|
|
632
|
-
qualifiedSubjectId
|
|
633
|
-
]);
|
|
634
|
-
const attendableAttrs = createAttendableAttributes(qualifiedSubjectId);
|
|
635
|
-
const { showResolvedThreads } = getViewState(qualifiedSubjectId);
|
|
636
|
-
return /* @__PURE__ */ React5.createElement("div", {
|
|
637
|
-
role: "none",
|
|
638
|
-
className: "contents group/attention",
|
|
639
|
-
...attendableAttrs
|
|
640
|
-
}, role === "complementary" && /* @__PURE__ */ React5.createElement(CommentsHeading, {
|
|
641
|
-
attendableId: qualifiedSubjectId
|
|
642
|
-
}), /* @__PURE__ */ React5.createElement(ScrollArea.Root, {
|
|
643
|
-
classNames: "row-span-2"
|
|
644
|
-
}, /* @__PURE__ */ React5.createElement(ScrollArea.Viewport, null, /* @__PURE__ */ React5.createElement(CommentsContainer, {
|
|
645
|
-
threads,
|
|
646
|
-
detached,
|
|
647
|
-
currentId: attention.has(qualifiedSubjectId) ? state.current : void 0,
|
|
648
|
-
autoFocusCurrentTextbox: state.focus,
|
|
649
|
-
showResolvedThreads,
|
|
650
|
-
onThreadAttend: (thread) => {
|
|
651
|
-
if (state.current !== thread.id) {
|
|
652
|
-
state.current = thread.id;
|
|
653
|
-
void dispatch?.({
|
|
654
|
-
action: LayoutAction.SCROLL_INTO_VIEW,
|
|
655
|
-
data: {
|
|
656
|
-
id: fullyQualifiedId(data.subject),
|
|
657
|
-
thread: fullyQualifiedId(thread),
|
|
658
|
-
cursor: thread.anchor
|
|
659
|
-
}
|
|
660
|
-
});
|
|
661
|
-
}
|
|
662
|
-
},
|
|
663
|
-
onThreadDelete: (thread) => dispatch?.({
|
|
664
|
-
plugin: THREAD_PLUGIN,
|
|
665
|
-
action: ThreadAction.DELETE,
|
|
666
|
-
data: {
|
|
667
|
-
subject: data.subject,
|
|
668
|
-
thread
|
|
669
|
-
}
|
|
670
|
-
}),
|
|
671
|
-
onMessageDelete: (thread, messageId) => dispatch?.({
|
|
672
|
-
plugin: THREAD_PLUGIN,
|
|
673
|
-
action: ThreadAction.DELETE_MESSAGE,
|
|
674
|
-
data: {
|
|
675
|
-
subject: data.subject,
|
|
676
|
-
thread,
|
|
677
|
-
messageId
|
|
678
|
-
}
|
|
679
|
-
}),
|
|
680
|
-
onThreadToggleResolved: (thread) => dispatch?.({
|
|
681
|
-
plugin: THREAD_PLUGIN,
|
|
682
|
-
action: ThreadAction.TOGGLE_RESOLVED,
|
|
683
|
-
data: {
|
|
684
|
-
thread
|
|
685
|
-
}
|
|
686
|
-
}),
|
|
687
|
-
onComment: (thread) => {
|
|
688
|
-
void intentPlugin?.provides.intent.dispatch({
|
|
689
|
-
action: ThreadAction.ON_MESSAGE_ADD,
|
|
690
|
-
data: {
|
|
691
|
-
thread,
|
|
692
|
-
subject: data.subject
|
|
693
|
-
}
|
|
694
|
-
});
|
|
695
|
-
}
|
|
696
|
-
}), /* @__PURE__ */ React5.createElement("div", {
|
|
697
|
-
role: "none",
|
|
698
|
-
className: "bs-10"
|
|
699
|
-
}), /* @__PURE__ */ React5.createElement(ScrollArea.Scrollbar, null, /* @__PURE__ */ React5.createElement(ScrollArea.Thumb, null)))));
|
|
774
|
+
const { showResolvedThreads } = getViewState(fullyQualifiedId5(data.subject));
|
|
775
|
+
return /* @__PURE__ */ React6.createElement(ThreadComplementary, {
|
|
776
|
+
role,
|
|
777
|
+
subject: data.subject,
|
|
778
|
+
drafts: state.drafts[fullyQualifiedId5(data.subject)],
|
|
779
|
+
current: state.current,
|
|
780
|
+
showResolvedThreads
|
|
781
|
+
});
|
|
700
782
|
}
|
|
783
|
+
break;
|
|
701
784
|
}
|
|
702
785
|
}
|
|
703
786
|
return null;
|
|
@@ -709,18 +792,31 @@ var ThreadPlugin = () => {
|
|
|
709
792
|
case ThreadAction.CREATE: {
|
|
710
793
|
if (intent.data && intent.data.cursor !== void 0) {
|
|
711
794
|
const { cursor, name, subject } = intent.data;
|
|
712
|
-
|
|
713
|
-
|
|
795
|
+
if (subject?.threads === void 0) {
|
|
796
|
+
try {
|
|
797
|
+
subject.threads = [];
|
|
798
|
+
} catch (err) {
|
|
799
|
+
log.error("Subject does not support threads array", subject?.typename, {
|
|
800
|
+
F: __dxlog_file,
|
|
801
|
+
L: 322,
|
|
802
|
+
S: void 0,
|
|
803
|
+
C: (f, a) => f(...a)
|
|
804
|
+
});
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
const subjectId = fullyQualifiedId5(subject);
|
|
809
|
+
const thread = create2(ThreadType2, {
|
|
714
810
|
name,
|
|
715
811
|
anchor: cursor,
|
|
716
812
|
messages: [],
|
|
717
813
|
status: "staged"
|
|
718
814
|
});
|
|
719
|
-
const
|
|
720
|
-
if (
|
|
721
|
-
|
|
815
|
+
const draft = state.drafts[subjectId];
|
|
816
|
+
if (draft) {
|
|
817
|
+
draft.push(thread);
|
|
722
818
|
} else {
|
|
723
|
-
state.
|
|
819
|
+
state.drafts[subjectId] = [
|
|
724
820
|
thread
|
|
725
821
|
];
|
|
726
822
|
}
|
|
@@ -728,27 +824,20 @@ var ThreadPlugin = () => {
|
|
|
728
824
|
data: thread,
|
|
729
825
|
intents: [
|
|
730
826
|
[
|
|
731
|
-
{
|
|
732
|
-
action: NavigationAction.OPEN,
|
|
733
|
-
data: {
|
|
734
|
-
activeParts: {
|
|
735
|
-
complementary: `${subjectId}${SLUG_PATH_SEPARATOR}comments${SLUG_COLLECTION_INDICATOR}`
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
},
|
|
739
827
|
{
|
|
740
828
|
action: ThreadAction.SELECT,
|
|
741
829
|
data: {
|
|
742
|
-
current: thread
|
|
743
|
-
focus: true
|
|
830
|
+
current: fullyQualifiedId5(thread)
|
|
744
831
|
}
|
|
745
|
-
}
|
|
832
|
+
}
|
|
833
|
+
],
|
|
834
|
+
[
|
|
746
835
|
{
|
|
747
|
-
action:
|
|
836
|
+
action: NavigationAction.OPEN,
|
|
748
837
|
data: {
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
838
|
+
activeParts: {
|
|
839
|
+
complementary: "comments"
|
|
840
|
+
}
|
|
752
841
|
}
|
|
753
842
|
}
|
|
754
843
|
]
|
|
@@ -758,7 +847,7 @@ var ThreadPlugin = () => {
|
|
|
758
847
|
return {
|
|
759
848
|
data: create2(ChannelType, {
|
|
760
849
|
threads: [
|
|
761
|
-
create2(
|
|
850
|
+
create2(ThreadType2, {
|
|
762
851
|
messages: []
|
|
763
852
|
})
|
|
764
853
|
]
|
|
@@ -767,15 +856,26 @@ var ThreadPlugin = () => {
|
|
|
767
856
|
}
|
|
768
857
|
}
|
|
769
858
|
case ThreadAction.SELECT: {
|
|
770
|
-
state.focus = intent.data?.current === state.current ? state.focus : intent.data?.focus;
|
|
771
859
|
state.current = intent.data?.current;
|
|
772
860
|
return {
|
|
773
|
-
data: true
|
|
861
|
+
data: true,
|
|
862
|
+
intents: !intent.data?.skipOpen ? [
|
|
863
|
+
[
|
|
864
|
+
{
|
|
865
|
+
action: NavigationAction.OPEN,
|
|
866
|
+
data: {
|
|
867
|
+
activeParts: {
|
|
868
|
+
complementary: "comments"
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
]
|
|
873
|
+
] : []
|
|
774
874
|
};
|
|
775
875
|
}
|
|
776
876
|
case ThreadAction.TOGGLE_RESOLVED: {
|
|
777
877
|
const { thread } = intent.data ?? {};
|
|
778
|
-
if (!(thread instanceof
|
|
878
|
+
if (!(thread instanceof ThreadType2)) {
|
|
779
879
|
return;
|
|
780
880
|
}
|
|
781
881
|
if (thread.status === "active" || thread.status === void 0) {
|
|
@@ -783,9 +883,10 @@ var ThreadPlugin = () => {
|
|
|
783
883
|
} else if (thread.status === "resolved") {
|
|
784
884
|
thread.status = "active";
|
|
785
885
|
}
|
|
786
|
-
const space =
|
|
886
|
+
const space = getSpace3(thread);
|
|
787
887
|
const spaceId = space?.id;
|
|
788
888
|
return {
|
|
889
|
+
data: true,
|
|
789
890
|
intents: [
|
|
790
891
|
[
|
|
791
892
|
{
|
|
@@ -804,19 +905,21 @@ var ThreadPlugin = () => {
|
|
|
804
905
|
}
|
|
805
906
|
case ThreadAction.DELETE: {
|
|
806
907
|
const { subject, thread } = intent.data ?? {};
|
|
807
|
-
if (!(
|
|
908
|
+
if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject)) {
|
|
808
909
|
return;
|
|
809
910
|
}
|
|
810
|
-
const subjectId =
|
|
811
|
-
const
|
|
812
|
-
if (
|
|
813
|
-
const index =
|
|
911
|
+
const subjectId = fullyQualifiedId5(subject);
|
|
912
|
+
const draft = state.drafts[subjectId];
|
|
913
|
+
if (draft) {
|
|
914
|
+
const index = draft.findIndex((t) => t.id === thread.id);
|
|
814
915
|
if (index !== -1) {
|
|
815
|
-
|
|
816
|
-
return
|
|
916
|
+
draft.splice(index, 1);
|
|
917
|
+
return {
|
|
918
|
+
data: true
|
|
919
|
+
};
|
|
817
920
|
}
|
|
818
921
|
}
|
|
819
|
-
const space =
|
|
922
|
+
const space = getSpace3(thread);
|
|
820
923
|
if (!space || !subject.threads) {
|
|
821
924
|
return;
|
|
822
925
|
}
|
|
@@ -874,22 +977,22 @@ var ThreadPlugin = () => {
|
|
|
874
977
|
}
|
|
875
978
|
case ThreadAction.ON_MESSAGE_ADD: {
|
|
876
979
|
const { thread, subject } = intent.data ?? {};
|
|
877
|
-
if (!(thread instanceof
|
|
980
|
+
if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject && Array.isArray(subject.threads))) {
|
|
878
981
|
return;
|
|
879
982
|
}
|
|
880
|
-
const subjectId =
|
|
881
|
-
const space =
|
|
983
|
+
const subjectId = fullyQualifiedId5(subject);
|
|
984
|
+
const space = getSpace3(subject);
|
|
882
985
|
const intents = [];
|
|
883
986
|
const analyticsProperties = {
|
|
884
987
|
threadId: thread.id,
|
|
885
988
|
spaceId: space?.id
|
|
886
989
|
};
|
|
887
|
-
if (state.
|
|
990
|
+
if (state.drafts[subjectId]?.find((t) => t === thread)) {
|
|
888
991
|
thread.status = "active";
|
|
889
992
|
subject.threads ? subject.threads.push(thread) : subject.threads = [
|
|
890
993
|
thread
|
|
891
994
|
];
|
|
892
|
-
state.
|
|
995
|
+
state.drafts[subjectId] = state.drafts[subjectId]?.filter(({ id }) => id !== thread.id);
|
|
893
996
|
intents.push({
|
|
894
997
|
action: ObservabilityAction.SEND_EVENT,
|
|
895
998
|
data: {
|
|
@@ -917,8 +1020,8 @@ var ThreadPlugin = () => {
|
|
|
917
1020
|
}
|
|
918
1021
|
case ThreadAction.DELETE_MESSAGE: {
|
|
919
1022
|
const { subject, thread, messageId } = intent.data ?? {};
|
|
920
|
-
const space =
|
|
921
|
-
if (!(
|
|
1023
|
+
const space = getSpace3(subject);
|
|
1024
|
+
if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject)) {
|
|
922
1025
|
return;
|
|
923
1026
|
}
|
|
924
1027
|
if (!intent.undo) {
|
|
@@ -960,7 +1063,7 @@ var ThreadPlugin = () => {
|
|
|
960
1063
|
name: "threads.message.delete",
|
|
961
1064
|
properties: {
|
|
962
1065
|
threadId: thread.id,
|
|
963
|
-
spaceId: space
|
|
1066
|
+
spaceId: space?.id
|
|
964
1067
|
}
|
|
965
1068
|
}
|
|
966
1069
|
}
|
|
@@ -984,7 +1087,7 @@ var ThreadPlugin = () => {
|
|
|
984
1087
|
name: "threads.message.undo-delete",
|
|
985
1088
|
properties: {
|
|
986
1089
|
threadId: thread.id,
|
|
987
|
-
spaceId: space
|
|
1090
|
+
spaceId: space?.id
|
|
988
1091
|
}
|
|
989
1092
|
}
|
|
990
1093
|
}
|
|
@@ -997,92 +1100,8 @@ var ThreadPlugin = () => {
|
|
|
997
1100
|
}
|
|
998
1101
|
},
|
|
999
1102
|
markdown: {
|
|
1000
|
-
// TODO(burdon): Factor out extension factory into separate file (for simplicity).
|
|
1001
1103
|
extensions: ({ document: doc }) => {
|
|
1002
|
-
|
|
1003
|
-
if (!doc || !space) {
|
|
1004
|
-
return [
|
|
1005
|
-
comments()
|
|
1006
|
-
];
|
|
1007
|
-
}
|
|
1008
|
-
const threads = computed(() => [
|
|
1009
|
-
...doc.threads.filter(nonNullable2),
|
|
1010
|
-
...state.staging[fullyQualifiedId(doc)] ?? []
|
|
1011
|
-
].filter((thread) => !(thread?.status === "resolved")));
|
|
1012
|
-
return [
|
|
1013
|
-
listener2({
|
|
1014
|
-
onChange: () => {
|
|
1015
|
-
doc.threads.forEach((thread) => {
|
|
1016
|
-
if (thread?.anchor) {
|
|
1017
|
-
const [start, end] = thread.anchor.split(":");
|
|
1018
|
-
const name = doc.content && getTextInRange(createDocAccessor(doc.content, [
|
|
1019
|
-
"content"
|
|
1020
|
-
]), start, end);
|
|
1021
|
-
if (name && name !== thread.name) {
|
|
1022
|
-
thread.name = name;
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
});
|
|
1026
|
-
}
|
|
1027
|
-
}),
|
|
1028
|
-
createExternalCommentSync(doc.id, (sink) => effect(() => sink()), () => threads.value.filter((thread) => thread?.anchor).map((thread) => ({
|
|
1029
|
-
id: thread.id,
|
|
1030
|
-
cursor: thread.anchor
|
|
1031
|
-
}))),
|
|
1032
|
-
comments({
|
|
1033
|
-
id: doc.id,
|
|
1034
|
-
onCreate: ({ cursor }) => {
|
|
1035
|
-
const [start, end] = cursor.split(":");
|
|
1036
|
-
const name = doc.content && getTextInRange(createDocAccessor(doc.content, [
|
|
1037
|
-
"content"
|
|
1038
|
-
]), start, end);
|
|
1039
|
-
void intentPlugin?.provides.intent.dispatch({
|
|
1040
|
-
action: ThreadAction.CREATE,
|
|
1041
|
-
data: {
|
|
1042
|
-
cursor,
|
|
1043
|
-
name,
|
|
1044
|
-
subject: doc
|
|
1045
|
-
}
|
|
1046
|
-
});
|
|
1047
|
-
},
|
|
1048
|
-
onDelete: ({ id }) => {
|
|
1049
|
-
const stagingArea = state.staging[fullyQualifiedId(doc)];
|
|
1050
|
-
if (stagingArea) {
|
|
1051
|
-
const index = stagingArea.findIndex((thread2) => thread2.id === id);
|
|
1052
|
-
if (index !== -1) {
|
|
1053
|
-
stagingArea.splice(index, 1);
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
const thread = doc.threads.find((thread2) => thread2?.id === id);
|
|
1057
|
-
if (thread) {
|
|
1058
|
-
thread.anchor = void 0;
|
|
1059
|
-
}
|
|
1060
|
-
},
|
|
1061
|
-
onUpdate: ({ id, cursor }) => {
|
|
1062
|
-
const thread = state.staging[fullyQualifiedId(doc)]?.find((thread2) => thread2.id === id) ?? doc.threads.find((thread2) => thread2?.id === id);
|
|
1063
|
-
if (thread instanceof ThreadType && thread.anchor) {
|
|
1064
|
-
const [start, end] = thread.anchor.split(":");
|
|
1065
|
-
thread.name = doc.content && getTextInRange(createDocAccessor(doc.content, [
|
|
1066
|
-
"content"
|
|
1067
|
-
]), start, end);
|
|
1068
|
-
thread.anchor = cursor;
|
|
1069
|
-
}
|
|
1070
|
-
},
|
|
1071
|
-
onSelect: ({ selection: { current, closest } }) => {
|
|
1072
|
-
const dispatch2 = intentPlugin?.provides.intent.dispatch;
|
|
1073
|
-
if (dispatch2) {
|
|
1074
|
-
void dispatch2([
|
|
1075
|
-
{
|
|
1076
|
-
action: ThreadAction.SELECT,
|
|
1077
|
-
data: {
|
|
1078
|
-
current: current ?? closest
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
]);
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1084
|
-
})
|
|
1085
|
-
];
|
|
1104
|
+
return threads(state, doc, intentPlugin?.provides.intent.dispatch);
|
|
1086
1105
|
}
|
|
1087
1106
|
}
|
|
1088
1107
|
}
|