@dxos/plugin-thread 0.6.11-staging.e6894a4 → 0.6.12-main.5cc132e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/lib/browser/{ThreadArticle-O64ZECMF.mjs → ThreadArticle-6L6BGE4Z.mjs} +2 -2
  2. package/dist/lib/browser/{ThreadMain-ZDCRC6RG.mjs → ThreadMain-DU6LBSN3.mjs} +2 -2
  3. package/dist/lib/browser/{chunk-P7ZE5N5M.mjs → chunk-AVC4CGJM.mjs} +6 -6
  4. package/dist/lib/browser/chunk-AVC4CGJM.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-GKPZHUT3.mjs → chunk-U5UVX4ZP.mjs} +1 -1
  6. package/dist/lib/browser/{chunk-GKPZHUT3.mjs.map → chunk-U5UVX4ZP.mjs.map} +1 -1
  7. package/dist/lib/browser/index.mjs +217 -156
  8. package/dist/lib/browser/index.mjs.map +4 -4
  9. package/dist/lib/browser/meta.json +1 -1
  10. package/dist/lib/browser/types.mjs +1 -1
  11. package/dist/lib/node/{ThreadArticle-DO56JXBU.cjs → ThreadArticle-7BWXVIJ4.cjs} +6 -6
  12. package/dist/lib/node/{ThreadMain-XJX75GHG.cjs → ThreadMain-XSRB6NKJ.cjs} +6 -6
  13. package/dist/lib/node/{chunk-D5GOVXHS.cjs → chunk-4B2ARV7L.cjs} +4 -4
  14. package/dist/lib/node/{chunk-D5GOVXHS.cjs.map → chunk-4B2ARV7L.cjs.map} +1 -1
  15. package/dist/lib/node/{chunk-5PZNPPQF.cjs → chunk-T7TXCNHL.cjs} +8 -8
  16. package/dist/lib/node/chunk-T7TXCNHL.cjs.map +7 -0
  17. package/dist/lib/node/index.cjs +258 -199
  18. package/dist/lib/node/index.cjs.map +4 -4
  19. package/dist/lib/node/meta.json +1 -1
  20. package/dist/lib/node/types.cjs +2 -2
  21. package/dist/lib/node/types.cjs.map +1 -1
  22. package/dist/lib/node-esm/ThreadArticle-6L6BGE4Z.mjs +18 -0
  23. package/dist/lib/node-esm/ThreadArticle-6L6BGE4Z.mjs.map +7 -0
  24. package/dist/lib/node-esm/ThreadMain-DU6LBSN3.mjs +26 -0
  25. package/dist/lib/node-esm/ThreadMain-DU6LBSN3.mjs.map +7 -0
  26. package/dist/lib/node-esm/chunk-5IBJO53M.mjs +21 -0
  27. package/dist/lib/node-esm/chunk-5IBJO53M.mjs.map +7 -0
  28. package/dist/lib/node-esm/chunk-AVC4CGJM.mjs +410 -0
  29. package/dist/lib/node-esm/chunk-AVC4CGJM.mjs.map +7 -0
  30. package/dist/lib/node-esm/chunk-U5UVX4ZP.mjs +20 -0
  31. package/dist/lib/node-esm/chunk-U5UVX4ZP.mjs.map +7 -0
  32. package/dist/lib/node-esm/index.mjs +1166 -0
  33. package/dist/lib/node-esm/index.mjs.map +7 -0
  34. package/dist/lib/node-esm/meta.json +1 -0
  35. package/dist/lib/node-esm/meta.mjs +11 -0
  36. package/dist/lib/node-esm/meta.mjs.map +7 -0
  37. package/dist/lib/node-esm/types.mjs +8 -0
  38. package/dist/lib/node-esm/types.mjs.map +7 -0
  39. package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
  40. package/dist/types/src/components/Chat.stories.d.ts +0 -1
  41. package/dist/types/src/components/Chat.stories.d.ts.map +1 -1
  42. package/dist/types/src/components/CommentContainer.d.ts.map +1 -1
  43. package/dist/types/src/components/Comments.stories.d.ts.map +1 -1
  44. package/dist/types/src/components/CommentsContainer.d.ts.map +1 -1
  45. package/dist/types/src/components/MessageContainer.d.ts.map +1 -1
  46. package/dist/types/src/components/ThreadComplementary.d.ts +11 -0
  47. package/dist/types/src/components/ThreadComplementary.d.ts.map +1 -0
  48. package/dist/types/src/types.d.ts +1 -1
  49. package/dist/types/src/types.d.ts.map +1 -1
  50. package/package.json +35 -32
  51. package/src/ThreadPlugin.tsx +49 -123
  52. package/src/components/Chat.stories.tsx +3 -3
  53. package/src/components/ChatContainer.tsx +4 -4
  54. package/src/components/CommentContainer.tsx +10 -7
  55. package/src/components/Comments.stories.tsx +10 -15
  56. package/src/components/CommentsContainer.tsx +18 -14
  57. package/src/components/MessageContainer.tsx +2 -1
  58. package/src/components/ThreadComplementary.tsx +120 -0
  59. package/src/types.ts +1 -1
  60. package/dist/lib/browser/chunk-P7ZE5N5M.mjs.map +0 -7
  61. package/dist/lib/node/chunk-5PZNPPQF.cjs.map +0 -7
  62. package/dist/types/src/types.test.d.ts +0 -2
  63. package/dist/types/src/types.test.d.ts.map +0 -1
  64. package/src/types.test.ts +0 -13
  65. /package/dist/lib/browser/{ThreadArticle-O64ZECMF.mjs.map → ThreadArticle-6L6BGE4Z.mjs.map} +0 -0
  66. /package/dist/lib/browser/{ThreadMain-ZDCRC6RG.mjs.map → ThreadMain-DU6LBSN3.mjs.map} +0 -0
  67. /package/dist/lib/node/{ThreadArticle-DO56JXBU.cjs.map → ThreadArticle-7BWXVIJ4.cjs.map} +0 -0
  68. /package/dist/lib/node/{ThreadMain-XJX75GHG.cjs.map → ThreadMain-XSRB6NKJ.cjs.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ThreadAction
3
- } from "./chunk-GKPZHUT3.mjs";
3
+ } from "./chunk-U5UVX4ZP.mjs";
4
4
  import {
5
5
  ChatContainer,
6
6
  ChatHeading,
@@ -10,7 +10,7 @@ import {
10
10
  useAnalyticsCallback,
11
11
  useOnEditAnalytics,
12
12
  useStatus
13
- } from "./chunk-P7ZE5N5M.mjs";
13
+ } from "./chunk-AVC4CGJM.mjs";
14
14
  import {
15
15
  THREAD_ITEM,
16
16
  THREAD_PLUGIN,
@@ -20,24 +20,22 @@ import {
20
20
  // packages/plugins/plugin-thread/src/ThreadPlugin.tsx
21
21
  import { Chat } from "@phosphor-icons/react";
22
22
  import { computed, effect } from "@preact/signals-core";
23
- import React5, { useCallback as useCallback2 } from "react";
24
- import { LayoutAction, NavigationAction, parseIntentPlugin, parseNavigationPlugin, resolvePlugin, parseGraphPlugin, SLUG_PATH_SEPARATOR, SLUG_COLLECTION_INDICATOR, isLayoutParts, parseMetadataResolverPlugin, useResolvePlugins } from "@dxos/app-framework";
23
+ import React6 from "react";
24
+ import { LayoutAction as LayoutAction2, NavigationAction, parseIntentPlugin, parseNavigationPlugin, resolvePlugin, parseGraphPlugin, SLUG_PATH_SEPARATOR, SLUG_COLLECTION_INDICATOR, isLayoutParts, parseMetadataResolverPlugin } from "@dxos/app-framework";
25
25
  import { getTypename } from "@dxos/echo-schema";
26
26
  import { create as create2 } from "@dxos/echo-schema";
27
27
  import { LocalStorageStore } from "@dxos/local-storage";
28
+ import { log } from "@dxos/log";
28
29
  import { parseAttentionPlugin } from "@dxos/plugin-attention";
29
30
  import { parseClientPlugin } from "@dxos/plugin-client";
30
31
  import { createExtension, isActionGroup } from "@dxos/plugin-graph";
31
- import { DocumentType } from "@dxos/plugin-markdown/types";
32
32
  import { ObservabilityAction } from "@dxos/plugin-observability/meta";
33
33
  import { SpaceAction } from "@dxos/plugin-space";
34
34
  import { ThreadType, MessageType as MessageType2, ChannelType } from "@dxos/plugin-space/types";
35
- import { getSpace as getSpace2, getTextInRange, Filter, createDocAccessor, fullyQualifiedId, loadObjectReferences } from "@dxos/react-client/echo";
36
- import { ScrollArea } from "@dxos/react-ui";
37
- import { createAttendableAttributes } from "@dxos/react-ui-attention";
35
+ import { getSpace as getSpace2, getTextInRange, Filter, createDocAccessor, fullyQualifiedId as fullyQualifiedId4, loadObjectReferences } from "@dxos/react-client/echo";
38
36
  import { comments, createExternalCommentSync, listener as listener2 } from "@dxos/react-ui-editor";
39
37
  import { translations as threadTranslations } from "@dxos/react-ui-thread";
40
- import { nonNullable as nonNullable2 } from "@dxos/util";
38
+ import { nonNullable as nonNullable3 } from "@dxos/util";
41
39
 
42
40
  // packages/plugins/plugin-thread/src/components/index.ts
43
41
  import React4 from "react";
@@ -61,7 +59,7 @@ import { CheckCircle, X } from "@phosphor-icons/react";
61
59
  import React2, { useCallback, useEffect, useMemo, useRef, useState } from "react";
62
60
  import { create } from "@dxos/echo-schema";
63
61
  import { MessageType } from "@dxos/plugin-space/types";
64
- import { getSpace, useMembers } from "@dxos/react-client/echo";
62
+ import { fullyQualifiedId, getSpace, useMembers } from "@dxos/react-client/echo";
65
63
  import { useIdentity } from "@dxos/react-client/halo";
66
64
  import { Button, Tag, Tooltip, useThemeContext, useTranslation as useTranslation2 } from "@dxos/react-ui";
67
65
  import { createBasicExtensions, createThemeExtensions, listener } from "@dxos/react-ui-editor";
@@ -118,12 +116,12 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
118
116
  const identity = useIdentity();
119
117
  const space = getSpace(thread);
120
118
  const members = useMembers(space?.key);
121
- const activity = useStatus(space, thread.id);
119
+ const activity = useStatus(space, fullyQualifiedId(thread));
122
120
  const { t } = useTranslation2(THREAD_PLUGIN);
123
121
  const threadScrollRef = useRef(null);
124
122
  const [autoFocus, setAutoFocus] = useState(!!autoFocusTextbox);
125
123
  const { themeMode } = useThemeContext();
126
- const textboxMetadata = getMessageMetadata(thread.id, identity);
124
+ const textboxMetadata = getMessageMetadata(fullyQualifiedId(thread), identity);
127
125
  const [_count, _setCount] = useState(0);
128
126
  const rerenderEditor = () => _setCount((count) => count + 1);
129
127
  const messageRef = useRef("");
@@ -172,12 +170,11 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
172
170
  thread,
173
171
  identity
174
172
  ]);
175
- const handleDeleteMessage = (id) => onMessageDelete?.(id);
176
173
  return /* @__PURE__ */ React2.createElement(Thread, {
177
174
  onClickCapture: onAttend,
178
175
  onFocusCapture: onAttend,
179
176
  current,
180
- id: thread.id
177
+ id: fullyQualifiedId(thread)
181
178
  }, /* @__PURE__ */ React2.createElement("div", {
182
179
  role: "none",
183
180
  className: mx("col-span-2 grid grid-cols-[var(--rail-size)_1fr_min-content]", hoverableControls, hoverableFocusedWithinControls)
@@ -201,7 +198,7 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
201
198
  key: message.id,
202
199
  message,
203
200
  members,
204
- onDelete: handleDeleteMessage
201
+ onDelete: (id) => onMessageDelete?.(id)
205
202
  })), /* @__PURE__ */ React2.createElement(MessageTextbox, {
206
203
  extensions,
207
204
  autoFocus,
@@ -219,6 +216,7 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
219
216
  // packages/plugins/plugin-thread/src/components/CommentsContainer.tsx
220
217
  import { ChatText, Quotes } from "@phosphor-icons/react";
221
218
  import React3, { useEffect as useEffect2 } from "react";
219
+ import { fullyQualifiedId as fullyQualifiedId2 } from "@dxos/react-client/echo";
222
220
  import { useTranslation as useTranslation3, Trans } from "@dxos/react-ui";
223
221
  import { PlankHeading, plankHeadingIconProps } from "@dxos/react-ui-deck";
224
222
  import { descriptionText, mx as mx2 } from "@dxos/react-ui-theme";
@@ -246,26 +244,29 @@ var CommentsContainer = ({ threads, detached = [], currentId, autoFocusCurrentTe
246
244
  }, [
247
245
  currentId
248
246
  ]);
249
- return /* @__PURE__ */ React3.createElement(React3.Fragment, null, filteredThreads.length > 0 ? filteredThreads.map((thread) => /* @__PURE__ */ React3.createElement(CommentContainer, {
250
- key: thread.id,
251
- thread,
252
- current: currentId === thread.id,
253
- detached: detached.includes(thread.id),
254
- autoFocusTextbox: autoFocusCurrentTextbox && currentId === thread.id,
255
- ...onThreadAttend && {
256
- onAttend: () => onThreadAttend(thread)
257
- },
258
- ...onThreadDelete && {
259
- onThreadDelete: () => onThreadDelete(thread)
260
- },
261
- ...onMessageDelete && {
262
- onMessageDelete: (messageId) => onMessageDelete(thread, messageId)
263
- },
264
- ...onThreadToggleResolved && {
265
- onResolve: () => onThreadToggleResolved(thread)
266
- },
267
- ...props
268
- })) : /* @__PURE__ */ React3.createElement("div", {
247
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, filteredThreads.length > 0 ? filteredThreads.map((thread) => {
248
+ const threadId = fullyQualifiedId2(thread);
249
+ return /* @__PURE__ */ React3.createElement(CommentContainer, {
250
+ key: threadId,
251
+ thread,
252
+ current: currentId === threadId,
253
+ detached: detached.includes(threadId),
254
+ autoFocusTextbox: autoFocusCurrentTextbox && currentId === threadId,
255
+ ...onThreadAttend && {
256
+ onAttend: () => onThreadAttend(thread)
257
+ },
258
+ ...onThreadDelete && {
259
+ onThreadDelete: () => onThreadDelete(thread)
260
+ },
261
+ ...onMessageDelete && {
262
+ onMessageDelete: (messageId) => onMessageDelete(thread, messageId)
263
+ },
264
+ ...onThreadToggleResolved && {
265
+ onResolve: () => onThreadToggleResolved(thread)
266
+ },
267
+ ...props
268
+ });
269
+ }) : /* @__PURE__ */ React3.createElement("div", {
269
270
  role: "alert",
270
271
  className: mx2(descriptionText, "place-self-center border border-dashed border-neutral-400/50 rounded-lg text-center p-4 m-4")
271
272
  }, /* @__PURE__ */ React3.createElement("h2", {
@@ -282,8 +283,124 @@ var CommentsContainer = ({ threads, detached = [], currentId, autoFocusCurrentTe
282
283
  };
283
284
 
284
285
  // packages/plugins/plugin-thread/src/components/index.ts
285
- var ThreadMain = React4.lazy(() => import("./ThreadMain-ZDCRC6RG.mjs"));
286
- var ThreadArticle = React4.lazy(() => import("./ThreadArticle-O64ZECMF.mjs"));
286
+ var ThreadMain = React4.lazy(() => import("./ThreadMain-DU6LBSN3.mjs"));
287
+ var ThreadArticle = React4.lazy(() => import("./ThreadArticle-6L6BGE4Z.mjs"));
288
+
289
+ // packages/plugins/plugin-thread/src/components/ThreadComplementary.tsx
290
+ import React5, { useEffect as useEffect3, useMemo as useMemo2 } from "react";
291
+ import { LayoutAction, useIntentDispatcher, useResolvePlugins } from "@dxos/app-framework";
292
+ import { fullyQualifiedId as fullyQualifiedId3 } from "@dxos/react-client/echo";
293
+ import { ScrollArea } from "@dxos/react-ui";
294
+ import { createAttendableAttributes, useAttentionContext } from "@dxos/react-ui-attention";
295
+ import { nonNullable as nonNullable2 } from "@dxos/util";
296
+ var providesThreadsConfig = (plugin) => "thread" in plugin.provides ? plugin : void 0;
297
+ var ThreadComplementary = ({ role, subject, stagedThreads, current, focus, showResolvedThreads }) => {
298
+ const dispatch = useIntentDispatcher();
299
+ const threadsIntegrators = useResolvePlugins(providesThreadsConfig);
300
+ const threadProvides = useMemo2(() => threadsIntegrators.map((p) => p.provides.thread), [
301
+ threadsIntegrators
302
+ ]);
303
+ const createSort = useMemo2(() => threadProvides.find((p) => p.predicate(subject))?.createSort, [
304
+ threadProvides,
305
+ subject
306
+ ]);
307
+ const sort = useMemo2(() => createSort?.(subject), [
308
+ createSort,
309
+ subject
310
+ ]);
311
+ const threads = useMemo2(() => {
312
+ return subject.threads.concat(stagedThreads ?? []).filter(nonNullable2);
313
+ }, [
314
+ JSON.stringify(subject.threads),
315
+ JSON.stringify(stagedThreads)
316
+ ]);
317
+ const detachedIds = useMemo2(() => {
318
+ return threads.filter(({ anchor }) => !anchor).map((thread) => fullyQualifiedId3(thread));
319
+ }, [
320
+ threads
321
+ ]);
322
+ useEffect3(() => {
323
+ if (!sort) {
324
+ return;
325
+ }
326
+ threads.sort((a, b) => sort(a?.anchor, b?.anchor));
327
+ }, [
328
+ sort,
329
+ threads
330
+ ]);
331
+ const { attended } = useAttentionContext("Thread Complementary");
332
+ const qualifiedSubjectId = fullyQualifiedId3(subject);
333
+ const attendableAttrs = createAttendableAttributes(qualifiedSubjectId);
334
+ return /* @__PURE__ */ React5.createElement("div", {
335
+ role: "none",
336
+ className: "contents group/attention",
337
+ ...attendableAttrs
338
+ }, role === "complementary" && /* @__PURE__ */ React5.createElement(CommentsHeading, {
339
+ attendableId: qualifiedSubjectId
340
+ }), /* @__PURE__ */ React5.createElement(ScrollArea.Root, {
341
+ classNames: "row-span-2"
342
+ }, /* @__PURE__ */ React5.createElement(ScrollArea.Viewport, null, /* @__PURE__ */ React5.createElement(CommentsContainer, {
343
+ threads,
344
+ detached: detachedIds,
345
+ currentId: attended.has(qualifiedSubjectId) ? current : void 0,
346
+ autoFocusCurrentTextbox: focus,
347
+ showResolvedThreads,
348
+ onThreadAttend: (thread) => {
349
+ const threadId = fullyQualifiedId3(thread);
350
+ if (current !== threadId) {
351
+ current = threadId;
352
+ void dispatch?.([
353
+ {
354
+ action: LayoutAction.SCROLL_INTO_VIEW,
355
+ data: {
356
+ id: fullyQualifiedId3(subject),
357
+ thread: threadId,
358
+ cursor: thread.anchor
359
+ }
360
+ }
361
+ ]);
362
+ }
363
+ },
364
+ onThreadDelete: (thread) => {
365
+ return dispatch({
366
+ plugin: THREAD_PLUGIN,
367
+ action: ThreadAction.DELETE,
368
+ data: {
369
+ subject,
370
+ thread
371
+ }
372
+ });
373
+ },
374
+ onMessageDelete: (thread, messageId) => dispatch({
375
+ plugin: THREAD_PLUGIN,
376
+ action: ThreadAction.DELETE_MESSAGE,
377
+ data: {
378
+ subject,
379
+ thread,
380
+ messageId
381
+ }
382
+ }),
383
+ onThreadToggleResolved: (thread) => dispatch({
384
+ plugin: THREAD_PLUGIN,
385
+ action: ThreadAction.TOGGLE_RESOLVED,
386
+ data: {
387
+ thread
388
+ }
389
+ }),
390
+ onComment: (thread) => {
391
+ void dispatch({
392
+ action: ThreadAction.ON_MESSAGE_ADD,
393
+ data: {
394
+ thread,
395
+ subject
396
+ }
397
+ });
398
+ }
399
+ }), /* @__PURE__ */ React5.createElement("div", {
400
+ role: "none",
401
+ className: "bs-10"
402
+ }), /* @__PURE__ */ React5.createElement(ScrollArea.Scrollbar, null, /* @__PURE__ */ React5.createElement(ScrollArea.Thumb, null)))));
403
+ };
287
404
 
288
405
  // packages/plugins/plugin-thread/src/translations.ts
289
406
  var translations_default = [
@@ -322,6 +439,7 @@ var translations_default = [
322
439
  ];
323
440
 
324
441
  // packages/plugins/plugin-thread/src/ThreadPlugin.tsx
442
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/plugin-thread/src/ThreadPlugin.tsx";
325
443
  var initialViewState = {
326
444
  showResolvedThreads: false
327
445
  };
@@ -342,7 +460,6 @@ var ThreadPlugin = () => {
342
460
  let attentionPlugin;
343
461
  let navigationPlugin;
344
462
  let intentPlugin;
345
- let dispatch;
346
463
  const unsubscribeCallbacks = [];
347
464
  return {
348
465
  meta: meta_default,
@@ -356,7 +473,6 @@ var ThreadPlugin = () => {
356
473
  attentionPlugin = resolvePlugin(plugins, parseAttentionPlugin);
357
474
  navigationPlugin = resolvePlugin(plugins, parseNavigationPlugin);
358
475
  intentPlugin = resolvePlugin(plugins, parseIntentPlugin);
359
- dispatch = intentPlugin?.provides.intent.dispatch;
360
476
  const graphPlugin = resolvePlugin(plugins, parseGraphPlugin);
361
477
  const client = resolvePlugin(plugins, parseClientPlugin)?.provides.client;
362
478
  if (!client) {
@@ -369,7 +485,10 @@ var ThreadPlugin = () => {
369
485
  if (!attention?.attended) {
370
486
  return;
371
487
  }
372
- 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);
488
+ const firstAttendedNodeWithComments = Array.from(attention.attended).map((id) => graphPlugin?.provides.graph.findNode(id)).find((node) => {
489
+ const data = node?.data;
490
+ return Array.isArray(data?.threads) && data.threads.length > 0;
491
+ });
373
492
  if (firstAttendedNodeWithComments) {
374
493
  void intentPlugin?.provides.intent.dispatch({
375
494
  action: NavigationAction.OPEN,
@@ -398,7 +517,7 @@ var ThreadPlugin = () => {
398
517
  ns: THREAD_PLUGIN
399
518
  }
400
519
  ],
401
- icon: (props) => /* @__PURE__ */ React5.createElement(Chat, props),
520
+ icon: (props) => /* @__PURE__ */ React6.createElement(Chat, props),
402
521
  iconSymbol: "ph--chat--regular",
403
522
  // TODO(wittjosiah): Move out of metadata.
404
523
  loadReferences: (channel) => loadObjectReferences(channel, (channel2) => channel2.threads)
@@ -446,9 +565,9 @@ var ThreadPlugin = () => {
446
565
  graph: {
447
566
  builder: (plugins) => {
448
567
  const client = resolvePlugin(plugins, parseClientPlugin)?.provides.client;
449
- const dispatch2 = resolvePlugin(plugins, parseIntentPlugin)?.provides.intent.dispatch;
568
+ const dispatch = resolvePlugin(plugins, parseIntentPlugin)?.provides.intent.dispatch;
450
569
  const metadataResolver = resolvePlugin(plugins, parseMetadataResolverPlugin)?.provides.metadata.resolver;
451
- if (!client || !dispatch2 || !metadataResolver) {
570
+ if (!client || !dispatch || !metadataResolver) {
452
571
  return [];
453
572
  }
454
573
  return [
@@ -494,7 +613,7 @@ var ThreadPlugin = () => {
494
613
  const toggle = () => {
495
614
  const newToggleState = !viewState.showResolvedThreads;
496
615
  viewState.showResolvedThreads = newToggleState;
497
- void dispatch2({
616
+ void dispatch({
498
617
  action: ObservabilityAction.SEND_EVENT,
499
618
  data: {
500
619
  name: "threads.toggle-show-resolved",
@@ -519,7 +638,8 @@ var ThreadPlugin = () => {
519
638
  ],
520
639
  menuItemType: "toggle",
521
640
  isChecked: viewState.showResolvedThreads,
522
- testId: "threadPlugin.toggleShowResolved"
641
+ testId: "threadPlugin.toggleShowResolved",
642
+ iconSymbol: viewState.showResolvedThreads ? "ph--eye-slash--regular" : "ph--eye--regular"
523
643
  }
524
644
  }
525
645
  ];
@@ -541,7 +661,7 @@ var ThreadPlugin = () => {
541
661
  {
542
662
  id: `${THREAD_PLUGIN}/create/${node.id}`,
543
663
  data: async () => {
544
- await dispatch2([
664
+ await dispatch([
545
665
  {
546
666
  plugin: THREAD_PLUGIN,
547
667
  action: ThreadAction.CREATE
@@ -564,7 +684,7 @@ var ThreadPlugin = () => {
564
684
  ns: THREAD_PLUGIN
565
685
  }
566
686
  ],
567
- icon: (props) => /* @__PURE__ */ React5.createElement(Chat, props),
687
+ icon: (props) => /* @__PURE__ */ React6.createElement(Chat, props),
568
688
  iconSymbol: "ph--chat--regular",
569
689
  testId: "threadPlugin.createObject"
570
690
  }
@@ -579,24 +699,18 @@ var ThreadPlugin = () => {
579
699
  component: ({ data, role }) => {
580
700
  switch (role) {
581
701
  case "main": {
582
- return data.active instanceof ChannelType && data.active.threads[0] ? /* @__PURE__ */ React5.createElement(ThreadMain, {
702
+ return data.active instanceof ChannelType && data.active.threads[0] ? /* @__PURE__ */ React6.createElement(ThreadMain, {
583
703
  thread: data.active.threads[0]
584
704
  }) : null;
585
705
  }
586
706
  case "settings": {
587
- return data.plugin === meta_default.id ? /* @__PURE__ */ React5.createElement(ThreadSettings, {
707
+ return data.plugin === meta_default.id ? /* @__PURE__ */ React6.createElement(ThreadSettings, {
588
708
  settings: settings.values
589
709
  }) : null;
590
710
  }
591
711
  case "article":
592
712
  case "complementary": {
593
713
  const location = navigationPlugin?.provides.location;
594
- const providesThreadsConfig = useCallback2((plugin) => (
595
- // TODO(Zan): More robust runtime check.
596
- "thread" in plugin.provides ? plugin : void 0
597
- ), []);
598
- const threadsIntegrators = useResolvePlugins(providesThreadsConfig);
599
- const threadProvides = threadsIntegrators.map((p) => p.provides.thread);
600
714
  if (data.object instanceof ChannelType && data.object.threads[0]) {
601
715
  const channel = data.object;
602
716
  if (isLayoutParts(location?.active) && location.active.main) {
@@ -605,101 +719,33 @@ var ThreadPlugin = () => {
605
719
  if (currentPosition > 0) {
606
720
  const objectToTheLeft = layoutEntries[currentPosition - 1];
607
721
  const context = getSpace2(data.object)?.db.getObjectById(objectToTheLeft.id);
608
- return /* @__PURE__ */ React5.createElement(ThreadArticle, {
722
+ return /* @__PURE__ */ React6.createElement(ThreadArticle, {
609
723
  thread: data.object.threads[0],
610
724
  context
611
725
  });
612
726
  }
613
727
  }
614
- return /* @__PURE__ */ React5.createElement(ThreadArticle, {
728
+ return /* @__PURE__ */ React6.createElement(ThreadArticle, {
615
729
  thread: data.object.threads[0]
616
730
  });
617
731
  }
618
732
  if (data.subject instanceof ThreadType) {
619
- return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(ChatHeading, {
733
+ return /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(ChatHeading, {
620
734
  attendableId: data.subject.id
621
- }), /* @__PURE__ */ React5.createElement(ChatContainer, {
735
+ }), /* @__PURE__ */ React6.createElement(ChatContainer, {
622
736
  thread: data.subject
623
737
  }));
624
738
  }
625
739
  if (data.subject && typeof data.subject === "object" && "threads" in data.subject && Array.isArray(data.subject.threads)) {
626
- const threads = data.subject.threads.concat(state.staging[fullyQualifiedId(data.subject)]).filter(nonNullable2);
627
- const createSort = threadProvides.find((p) => p.predicate(data.subject))?.createSort;
628
- if (createSort) {
629
- const sort = createSort(data.subject);
630
- threads.sort((a, b) => sort(a.anchor, b.anchor));
631
- }
632
- const detached = data.subject.threads.filter(nonNullable2).filter(({ anchor }) => !anchor).map((thread) => thread.id);
633
- const qualifiedSubjectId = fullyQualifiedId(data.subject);
634
- const attention = attentionPlugin?.provides.attention?.attended ?? /* @__PURE__ */ new Set([
635
- qualifiedSubjectId
636
- ]);
637
- const attendableAttrs = createAttendableAttributes(qualifiedSubjectId);
638
- const { showResolvedThreads } = getViewState(qualifiedSubjectId);
639
- return /* @__PURE__ */ React5.createElement("div", {
640
- role: "none",
641
- className: "contents group/attention",
642
- ...attendableAttrs
643
- }, role === "complementary" && /* @__PURE__ */ React5.createElement(CommentsHeading, {
644
- attendableId: qualifiedSubjectId
645
- }), /* @__PURE__ */ React5.createElement(ScrollArea.Root, {
646
- classNames: "row-span-2"
647
- }, /* @__PURE__ */ React5.createElement(ScrollArea.Viewport, null, /* @__PURE__ */ React5.createElement(CommentsContainer, {
648
- threads,
649
- detached,
650
- currentId: attention.has(qualifiedSubjectId) ? state.current : void 0,
651
- autoFocusCurrentTextbox: state.focus,
652
- showResolvedThreads,
653
- onThreadAttend: (thread) => {
654
- if (state.current !== thread.id) {
655
- state.current = thread.id;
656
- void dispatch?.({
657
- action: LayoutAction.SCROLL_INTO_VIEW,
658
- data: {
659
- id: fullyQualifiedId(data.subject),
660
- thread: fullyQualifiedId(thread),
661
- cursor: thread.anchor
662
- }
663
- });
664
- }
665
- },
666
- onThreadDelete: (thread) => dispatch?.({
667
- plugin: THREAD_PLUGIN,
668
- action: ThreadAction.DELETE,
669
- data: {
670
- subject: data.subject,
671
- thread
672
- }
673
- }),
674
- onMessageDelete: (thread, messageId) => dispatch?.({
675
- plugin: THREAD_PLUGIN,
676
- action: ThreadAction.DELETE_MESSAGE,
677
- data: {
678
- subject: data.subject,
679
- thread,
680
- messageId
681
- }
682
- }),
683
- onThreadToggleResolved: (thread) => dispatch?.({
684
- plugin: THREAD_PLUGIN,
685
- action: ThreadAction.TOGGLE_RESOLVED,
686
- data: {
687
- thread
688
- }
689
- }),
690
- onComment: (thread) => {
691
- void intentPlugin?.provides.intent.dispatch({
692
- action: ThreadAction.ON_MESSAGE_ADD,
693
- data: {
694
- thread,
695
- subject: data.subject
696
- }
697
- });
698
- }
699
- }), /* @__PURE__ */ React5.createElement("div", {
700
- role: "none",
701
- className: "bs-10"
702
- }), /* @__PURE__ */ React5.createElement(ScrollArea.Scrollbar, null, /* @__PURE__ */ React5.createElement(ScrollArea.Thumb, null)))));
740
+ const { showResolvedThreads } = getViewState(fullyQualifiedId4(data.subject));
741
+ return /* @__PURE__ */ React6.createElement(ThreadComplementary, {
742
+ role,
743
+ subject: data.subject,
744
+ stagedThreads: state.staging[fullyQualifiedId4(data.subject)],
745
+ current: state.current,
746
+ focus: true,
747
+ showResolvedThreads
748
+ });
703
749
  }
704
750
  }
705
751
  }
@@ -712,7 +758,20 @@ var ThreadPlugin = () => {
712
758
  case ThreadAction.CREATE: {
713
759
  if (intent.data && intent.data.cursor !== void 0) {
714
760
  const { cursor, name, subject } = intent.data;
715
- const subjectId = fullyQualifiedId(subject);
761
+ if (subject?.threads === void 0) {
762
+ try {
763
+ subject.threads = [];
764
+ } catch (e) {
765
+ log.error("Subject does not support threads array", subject?.typename, {
766
+ F: __dxlog_file,
767
+ L: 369,
768
+ S: void 0,
769
+ C: (f, a) => f(...a)
770
+ });
771
+ return;
772
+ }
773
+ }
774
+ const subjectId = fullyQualifiedId4(subject);
716
775
  const thread = create2(ThreadType, {
717
776
  name,
718
777
  anchor: cursor,
@@ -742,12 +801,12 @@ var ThreadPlugin = () => {
742
801
  {
743
802
  action: ThreadAction.SELECT,
744
803
  data: {
745
- current: thread.id,
804
+ current: fullyQualifiedId4(thread),
746
805
  focus: true
747
806
  }
748
807
  },
749
808
  {
750
- action: LayoutAction.SET_LAYOUT,
809
+ action: LayoutAction2.SET_LAYOUT,
751
810
  data: {
752
811
  element: "complementary",
753
812
  subject: subjectId,
@@ -807,16 +866,18 @@ var ThreadPlugin = () => {
807
866
  }
808
867
  case ThreadAction.DELETE: {
809
868
  const { subject, thread } = intent.data ?? {};
810
- if (!(subject instanceof DocumentType) || !(thread instanceof ThreadType)) {
869
+ if (!(thread instanceof ThreadType) || !(subject && typeof subject === "object" && "threads" in subject)) {
811
870
  return;
812
871
  }
813
- const subjectId = fullyQualifiedId(subject);
872
+ const subjectId = fullyQualifiedId4(subject);
814
873
  const stagingArea = state.staging[subjectId];
815
874
  if (stagingArea) {
816
875
  const index = stagingArea.findIndex((t) => t.id === thread.id);
817
876
  if (index !== -1) {
818
877
  stagingArea.splice(index, 1);
819
- return;
878
+ return {
879
+ data: true
880
+ };
820
881
  }
821
882
  }
822
883
  const space = getSpace2(thread);
@@ -877,10 +938,10 @@ var ThreadPlugin = () => {
877
938
  }
878
939
  case ThreadAction.ON_MESSAGE_ADD: {
879
940
  const { thread, subject } = intent.data ?? {};
880
- if (!(thread instanceof ThreadType) || !(subject && typeof subject === "object" && "threads" in subject)) {
941
+ if (!(thread instanceof ThreadType) || !(subject && typeof subject === "object" && "threads" in subject && Array.isArray(subject.threads))) {
881
942
  return;
882
943
  }
883
- const subjectId = fullyQualifiedId(subject);
944
+ const subjectId = fullyQualifiedId4(subject);
884
945
  const space = getSpace2(subject);
885
946
  const intents = [];
886
947
  const analyticsProperties = {
@@ -921,7 +982,7 @@ var ThreadPlugin = () => {
921
982
  case ThreadAction.DELETE_MESSAGE: {
922
983
  const { subject, thread, messageId } = intent.data ?? {};
923
984
  const space = getSpace2(subject);
924
- if (!(subject instanceof DocumentType) || !(thread instanceof ThreadType) || !space) {
985
+ if (!(thread instanceof ThreadType) || !(subject && typeof subject === "object" && "threads" in subject)) {
925
986
  return;
926
987
  }
927
988
  if (!intent.undo) {
@@ -963,7 +1024,7 @@ var ThreadPlugin = () => {
963
1024
  name: "threads.message.delete",
964
1025
  properties: {
965
1026
  threadId: thread.id,
966
- spaceId: space.id
1027
+ spaceId: space?.id
967
1028
  }
968
1029
  }
969
1030
  }
@@ -987,7 +1048,7 @@ var ThreadPlugin = () => {
987
1048
  name: "threads.message.undo-delete",
988
1049
  properties: {
989
1050
  threadId: thread.id,
990
- spaceId: space.id
1051
+ spaceId: space?.id
991
1052
  }
992
1053
  }
993
1054
  }
@@ -1009,8 +1070,8 @@ var ThreadPlugin = () => {
1009
1070
  ];
1010
1071
  }
1011
1072
  const threads = computed(() => [
1012
- ...doc.threads.filter(nonNullable2),
1013
- ...state.staging[fullyQualifiedId(doc)] ?? []
1073
+ ...doc.threads.filter(nonNullable3),
1074
+ ...state.staging[fullyQualifiedId4(doc)] ?? []
1014
1075
  ].filter((thread) => !(thread?.status === "resolved")));
1015
1076
  return [
1016
1077
  listener2({
@@ -1029,7 +1090,7 @@ var ThreadPlugin = () => {
1029
1090
  }
1030
1091
  }),
1031
1092
  createExternalCommentSync(doc.id, (sink) => effect(() => sink()), () => threads.value.filter((thread) => thread?.anchor).map((thread) => ({
1032
- id: thread.id,
1093
+ id: fullyQualifiedId4(thread),
1033
1094
  cursor: thread.anchor
1034
1095
  }))),
1035
1096
  comments({
@@ -1049,9 +1110,9 @@ var ThreadPlugin = () => {
1049
1110
  });
1050
1111
  },
1051
1112
  onDelete: ({ id }) => {
1052
- const stagingArea = state.staging[fullyQualifiedId(doc)];
1113
+ const stagingArea = state.staging[fullyQualifiedId4(doc)];
1053
1114
  if (stagingArea) {
1054
- const index = stagingArea.findIndex((thread2) => thread2.id === id);
1115
+ const index = stagingArea.findIndex((thread2) => fullyQualifiedId4(thread2) === id);
1055
1116
  if (index !== -1) {
1056
1117
  stagingArea.splice(index, 1);
1057
1118
  }
@@ -1062,7 +1123,7 @@ var ThreadPlugin = () => {
1062
1123
  }
1063
1124
  },
1064
1125
  onUpdate: ({ id, cursor }) => {
1065
- const thread = state.staging[fullyQualifiedId(doc)]?.find((thread2) => thread2.id === id) ?? doc.threads.find((thread2) => thread2?.id === id);
1126
+ const thread = state.staging[fullyQualifiedId4(doc)]?.find((thread2) => fullyQualifiedId4(thread2) === id) ?? doc.threads.find((thread2) => thread2?.id === id);
1066
1127
  if (thread instanceof ThreadType && thread.anchor) {
1067
1128
  const [start, end] = thread.anchor.split(":");
1068
1129
  thread.name = doc.content && getTextInRange(createDocAccessor(doc.content, [
@@ -1072,9 +1133,9 @@ var ThreadPlugin = () => {
1072
1133
  }
1073
1134
  },
1074
1135
  onSelect: ({ selection: { current, closest } }) => {
1075
- const dispatch2 = intentPlugin?.provides.intent.dispatch;
1076
- if (dispatch2) {
1077
- void dispatch2([
1136
+ const dispatch = intentPlugin?.provides.intent.dispatch;
1137
+ if (dispatch) {
1138
+ void dispatch([
1078
1139
  {
1079
1140
  action: ThreadAction.SELECT,
1080
1141
  data: {