@dxos/plugin-thread 0.7.4 → 0.7.5-main.9d26e3a

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 (72) hide show
  1. package/dist/lib/browser/{ThreadArticle-6IXTL7CH.mjs → ThreadArticle-EWLTNU6Z.mjs} +2 -2
  2. package/dist/lib/browser/{ThreadMain-4IAS67KE.mjs → ThreadMain-ABEDFWHC.mjs} +2 -2
  3. package/dist/lib/browser/chunk-6KTMQPL4.mjs +77 -0
  4. package/dist/lib/browser/chunk-6KTMQPL4.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-52HWDLBR.mjs → chunk-OD2IZKRP.mjs} +23 -45
  6. package/dist/lib/browser/chunk-OD2IZKRP.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +323 -480
  8. package/dist/lib/browser/index.mjs.map +3 -3
  9. package/dist/lib/browser/meta.json +1 -1
  10. package/dist/lib/browser/types.mjs +1 -1
  11. package/dist/lib/node/{ThreadArticle-I7ADXDW3.cjs → ThreadArticle-ZCNMFBAO.cjs} +6 -6
  12. package/dist/lib/node/{ThreadMain-MRNJC3TI.cjs → ThreadMain-5AYGCXXP.cjs} +6 -6
  13. package/dist/lib/node/{chunk-YCDM2SZM.cjs → chunk-2CB5AVBL.cjs} +27 -50
  14. package/dist/lib/node/chunk-2CB5AVBL.cjs.map +7 -0
  15. package/dist/lib/node/chunk-VW2P26MZ.cjs +96 -0
  16. package/dist/lib/node/chunk-VW2P26MZ.cjs.map +7 -0
  17. package/dist/lib/node/index.cjs +336 -491
  18. package/dist/lib/node/index.cjs.map +3 -3
  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-CJHYMF2W.mjs → ThreadArticle-F37HYTOU.mjs} +2 -2
  23. package/dist/lib/node-esm/{ThreadMain-VISGW4IF.mjs → ThreadMain-OL6ZHNZY.mjs} +2 -2
  24. package/dist/lib/node-esm/{chunk-JG7MXH6O.mjs → chunk-AQ74G3GY.mjs} +23 -45
  25. package/dist/lib/node-esm/chunk-AQ74G3GY.mjs.map +7 -0
  26. package/dist/lib/node-esm/chunk-RMYATBXM.mjs +78 -0
  27. package/dist/lib/node-esm/chunk-RMYATBXM.mjs.map +7 -0
  28. package/dist/lib/node-esm/index.mjs +323 -480
  29. package/dist/lib/node-esm/index.mjs.map +3 -3
  30. package/dist/lib/node-esm/meta.json +1 -1
  31. package/dist/lib/node-esm/types.mjs +1 -1
  32. package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
  33. package/dist/types/src/components/Chat.stories.d.ts.map +1 -1
  34. package/dist/types/src/components/ChatContainer.d.ts.map +1 -1
  35. package/dist/types/src/components/CommentContainer.d.ts.map +1 -1
  36. package/dist/types/src/components/MessageContainer.d.ts.map +1 -1
  37. package/dist/types/src/components/ThreadComplementary.d.ts +1 -2
  38. package/dist/types/src/components/ThreadComplementary.d.ts.map +1 -1
  39. package/dist/types/src/components/testing.d.ts +50 -66
  40. package/dist/types/src/components/testing.d.ts.map +1 -1
  41. package/dist/types/src/extensions/threads.d.ts +2 -2
  42. package/dist/types/src/extensions/threads.d.ts.map +1 -1
  43. package/dist/types/src/hooks/analytics.d.ts.map +1 -1
  44. package/dist/types/src/types.d.ts +76 -8
  45. package/dist/types/src/types.d.ts.map +1 -1
  46. package/dist/types/tsconfig.tsbuildinfo +1 -0
  47. package/package.json +30 -30
  48. package/src/ThreadPlugin.tsx +215 -361
  49. package/src/components/Chat.stories.tsx +10 -8
  50. package/src/components/ChatContainer.tsx +13 -11
  51. package/src/components/CommentContainer.tsx +14 -11
  52. package/src/components/MessageContainer.tsx +7 -5
  53. package/src/components/ThreadComplementary.tsx +18 -32
  54. package/src/components/testing.ts +26 -22
  55. package/src/extensions/threads.ts +16 -25
  56. package/src/hooks/analytics.ts +6 -10
  57. package/src/types.ts +60 -9
  58. package/dist/lib/browser/chunk-52HWDLBR.mjs.map +0 -7
  59. package/dist/lib/browser/chunk-XUHNZID5.mjs +0 -20
  60. package/dist/lib/browser/chunk-XUHNZID5.mjs.map +0 -7
  61. package/dist/lib/node/chunk-XFO6D2LG.cjs +0 -39
  62. package/dist/lib/node/chunk-XFO6D2LG.cjs.map +0 -7
  63. package/dist/lib/node/chunk-YCDM2SZM.cjs.map +0 -7
  64. package/dist/lib/node-esm/chunk-I5MU54RT.mjs +0 -21
  65. package/dist/lib/node-esm/chunk-I5MU54RT.mjs.map +0 -7
  66. package/dist/lib/node-esm/chunk-JG7MXH6O.mjs.map +0 -7
  67. /package/dist/lib/browser/{ThreadArticle-6IXTL7CH.mjs.map → ThreadArticle-EWLTNU6Z.mjs.map} +0 -0
  68. /package/dist/lib/browser/{ThreadMain-4IAS67KE.mjs.map → ThreadMain-ABEDFWHC.mjs.map} +0 -0
  69. /package/dist/lib/node/{ThreadArticle-I7ADXDW3.cjs.map → ThreadArticle-ZCNMFBAO.cjs.map} +0 -0
  70. /package/dist/lib/node/{ThreadMain-MRNJC3TI.cjs.map → ThreadMain-5AYGCXXP.cjs.map} +0 -0
  71. /package/dist/lib/node-esm/{ThreadArticle-CJHYMF2W.mjs.map → ThreadArticle-F37HYTOU.mjs.map} +0 -0
  72. /package/dist/lib/node-esm/{ThreadMain-VISGW4IF.mjs.map → ThreadMain-OL6ZHNZY.mjs.map} +0 -0
@@ -1,16 +1,14 @@
1
1
  import {
2
2
  ThreadAction
3
- } from "./chunk-XUHNZID5.mjs";
3
+ } from "./chunk-6KTMQPL4.mjs";
4
4
  import {
5
- ChatContainer,
6
- ChatHeading,
7
5
  MessageContainer,
8
6
  command,
9
7
  getMessageMetadata,
10
8
  useAnalyticsCallback,
11
9
  useOnEditAnalytics,
12
10
  useStatus
13
- } from "./chunk-52HWDLBR.mjs";
11
+ } from "./chunk-OD2IZKRP.mjs";
14
12
  import {
15
13
  THREAD_ITEM,
16
14
  THREAD_PLUGIN,
@@ -19,15 +17,16 @@ import {
19
17
 
20
18
  // packages/plugins/plugin-thread/src/ThreadPlugin.tsx
21
19
  import React5 from "react";
22
- import { isLayoutParts, LayoutAction as LayoutAction2, NavigationAction, parseIntentPlugin, parseMetadataResolverPlugin, parseNavigationPlugin, resolvePlugin } from "@dxos/app-framework";
20
+ import { createIntent as createIntent3, createResolver, createSurface, isLayoutParts, LayoutAction as LayoutAction2, NavigationAction, parseIntentPlugin, parseMetadataResolverPlugin, parseNavigationPlugin, resolvePlugin } from "@dxos/app-framework";
21
+ import { Ref as Ref2 } from "@dxos/echo-schema";
23
22
  import { LocalStorageStore } from "@dxos/local-storage";
24
23
  import { log } from "@dxos/log";
25
- import { parseClientPlugin } from "@dxos/plugin-client";
26
- import { createExtension, isActionGroup, toSignal } from "@dxos/plugin-graph";
27
- import { ObservabilityAction } from "@dxos/plugin-observability/meta";
28
- import { memoizeQuery, SpaceAction } from "@dxos/plugin-space";
24
+ import { parseClientPlugin } from "@dxos/plugin-client/types";
25
+ import { createExtension, toSignal } from "@dxos/plugin-graph";
26
+ import { ObservabilityAction } from "@dxos/plugin-observability/types";
27
+ import { memoizeQuery } from "@dxos/plugin-space";
29
28
  import { ChannelType as ChannelType2, MessageType as MessageType2, ThreadType as ThreadType2 } from "@dxos/plugin-space/types";
30
- import { create as create2, fullyQualifiedId as fullyQualifiedId5, getSpace as getSpace3, getTypename, loadObjectReferences, parseId, SpaceState } from "@dxos/react-client/echo";
29
+ import { create as create2, fullyQualifiedId as fullyQualifiedId5, getSpace as getSpace3, getTypename, makeRef as makeRef2, parseId, RefArray as RefArray4, SpaceState } from "@dxos/react-client/echo";
31
30
  import { translations as threadTranslations } from "@dxos/react-ui-thread";
32
31
 
33
32
  // packages/plugins/plugin-thread/src/components/index.ts
@@ -36,7 +35,7 @@ import { lazy } from "react";
36
35
  // packages/plugins/plugin-thread/src/components/CommentContainer.tsx
37
36
  import { CheckCircle, X } from "@phosphor-icons/react";
38
37
  import React, { useCallback, useMemo, useRef, useState } from "react";
39
- import { create } from "@dxos/live-object";
38
+ import { create, makeRef, RefArray } from "@dxos/live-object";
40
39
  import { MessageType } from "@dxos/plugin-space/types";
41
40
  import { fullyQualifiedId, getSpace, useMembers } from "@dxos/react-client/echo";
42
41
  import { useIdentity } from "@dxos/react-client/halo";
@@ -67,9 +66,7 @@ var ToggleResolvedButton = ({ isResolved, onResolve }) => {
67
66
  weight: "fill"
68
67
  }) : /* @__PURE__ */ React.createElement(CheckCircle, {
69
68
  className: sizeClass
70
- }))), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, {
71
- classNames: "z-[21]"
72
- }, label, /* @__PURE__ */ React.createElement(Tooltip.Arrow, null))));
69
+ }))), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, null, label, /* @__PURE__ */ React.createElement(Tooltip.Arrow, null))));
73
70
  };
74
71
  var DeleteThreadButton = ({ onDelete }) => {
75
72
  const { t } = useTranslation(THREAD_PLUGIN);
@@ -89,7 +86,7 @@ var DeleteThreadButton = ({ onDelete }) => {
89
86
  }, label), /* @__PURE__ */ React.createElement(X, {
90
87
  className: sizeClass
91
88
  }))), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, {
92
- classNames: "z-[21]"
89
+ classNames: "z-30"
93
90
  }, label, /* @__PURE__ */ React.createElement(Tooltip.Arrow, null))));
94
91
  };
95
92
  var CommentContainer = ({ thread, detached, context, current, onAttend, onThreadDelete, onMessageDelete, onResolve, onComment }) => {
@@ -126,14 +123,14 @@ var CommentContainer = ({ thread, detached, context, current, onAttend, onThread
126
123
  if (!messageRef.current) {
127
124
  return false;
128
125
  }
129
- thread.messages.push(create(MessageType, {
126
+ thread.messages.push(makeRef(create(MessageType, {
130
127
  sender: {
131
128
  identityKey: identity.identityKey.toHex()
132
129
  },
133
130
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
134
131
  text: messageRef.current,
135
- context
136
- }));
132
+ context: context ? makeRef(context) : void 0
133
+ })));
137
134
  onComment?.(thread);
138
135
  messageRef.current = "";
139
136
  scrollToEnd("instant");
@@ -156,7 +153,7 @@ var CommentContainer = ({ thread, detached, context, current, onAttend, onThread
156
153
  }, /* @__PURE__ */ React.createElement(ThreadHeading, {
157
154
  detached: true
158
155
  }, thread.name)), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, {
159
- classNames: "z-[21]",
156
+ classNames: "z-30",
160
157
  side: "top"
161
158
  }, t("detached thread label"), /* @__PURE__ */ React.createElement(Tooltip.Arrow, null)))) : /* @__PURE__ */ React.createElement(ThreadHeading, null, thread.name), /* @__PURE__ */ React.createElement("div", {
162
159
  className: "flex flex-row items-center pli-1"
@@ -167,7 +164,7 @@ var CommentContainer = ({ thread, detached, context, current, onAttend, onThread
167
164
  onResolve
168
165
  }), onThreadDelete && /* @__PURE__ */ React.createElement(DeleteThreadButton, {
169
166
  onDelete: onThreadDelete
170
- }))), thread.messages.filter(nonNullable).map((message) => /* @__PURE__ */ React.createElement(MessageContainer, {
167
+ }))), RefArray.allResolvedTargets(thread.messages?.filter(nonNullable) ?? []).map((message) => /* @__PURE__ */ React.createElement(MessageContainer, {
171
168
  key: message.id,
172
169
  message,
173
170
  members,
@@ -243,13 +240,13 @@ var CommentsContainer = ({ threads: threads2, detached = [], currentId, showReso
243
240
 
244
241
  // packages/plugins/plugin-thread/src/components/ThreadComplementary.tsx
245
242
  import React3, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
246
- import { LayoutAction, useIntentDispatcher, useResolvePlugins } from "@dxos/app-framework";
247
- import { fullyQualifiedId as fullyQualifiedId3 } from "@dxos/react-client/echo";
243
+ import { createIntent, LayoutAction, useIntentDispatcher, useResolvePlugins } from "@dxos/app-framework";
244
+ import { fullyQualifiedId as fullyQualifiedId3, RefArray as RefArray2 } from "@dxos/react-client/echo";
248
245
  import { useAttended } from "@dxos/react-ui-attention";
249
246
  import { nonNullable as nonNullable2 } from "@dxos/util";
250
247
  var providesThreadsConfig = (plugin) => "thread" in plugin.provides ? plugin : void 0;
251
- var ThreadComplementary = ({ role, subject, drafts, current, showResolvedThreads }) => {
252
- const dispatch = useIntentDispatcher();
248
+ var ThreadComplementary = ({ subject, drafts, current, showResolvedThreads }) => {
249
+ const { dispatchPromise: dispatch } = useIntentDispatcher();
253
250
  const threadsIntegrators = useResolvePlugins(providesThreadsConfig);
254
251
  const threadProvides = useMemo2(() => threadsIntegrators.map((p) => p.provides.thread), [
255
252
  threadsIntegrators
@@ -262,10 +259,11 @@ var ThreadComplementary = ({ role, subject, drafts, current, showResolvedThreads
262
259
  createSort,
263
260
  subject
264
261
  ]);
262
+ const threadObjects = RefArray2.allResolvedTargets(subject.threads ?? []);
265
263
  const threads2 = useMemo2(() => {
266
- return subject.threads.concat(drafts ?? []).filter(nonNullable2);
264
+ return threadObjects.concat(drafts ?? []).filter(nonNullable2);
267
265
  }, [
268
- JSON.stringify(subject.threads),
266
+ JSON.stringify(threadObjects),
269
267
  JSON.stringify(drafts)
270
268
  ]);
271
269
  const detachedIds = useMemo2(() => {
@@ -293,53 +291,29 @@ var ThreadComplementary = ({ role, subject, drafts, current, showResolvedThreads
293
291
  const threadId = fullyQualifiedId3(thread);
294
292
  if (current !== threadId) {
295
293
  current = threadId;
296
- void dispatch?.([
297
- {
298
- action: LayoutAction.SCROLL_INTO_VIEW,
299
- data: {
300
- id: fullyQualifiedId3(subject),
301
- thread: threadId,
302
- cursor: thread.anchor
303
- }
304
- }
305
- ]);
294
+ void dispatch?.(createIntent(LayoutAction.ScrollIntoView, {
295
+ id: fullyQualifiedId3(subject),
296
+ cursor: thread.anchor,
297
+ ref: threadId
298
+ }));
306
299
  }
307
300
  },
308
- onThreadDelete: (thread) => {
309
- return dispatch({
310
- plugin: THREAD_PLUGIN,
311
- action: ThreadAction.DELETE,
312
- data: {
313
- subject,
314
- thread
315
- }
316
- });
317
- },
318
- onMessageDelete: (thread, messageId) => dispatch({
319
- plugin: THREAD_PLUGIN,
320
- action: ThreadAction.DELETE_MESSAGE,
321
- data: {
322
- subject,
323
- thread,
324
- messageId
325
- }
326
- }),
327
- onThreadToggleResolved: (thread) => dispatch({
328
- plugin: THREAD_PLUGIN,
329
- action: ThreadAction.TOGGLE_RESOLVED,
330
- data: {
331
- thread
332
- }
333
- }),
334
- onComment: (thread) => {
335
- void dispatch({
336
- action: ThreadAction.ON_MESSAGE_ADD,
337
- data: {
338
- thread,
339
- subject
340
- }
341
- });
342
- }
301
+ onThreadDelete: (thread) => dispatch(createIntent(ThreadAction.Delete, {
302
+ thread,
303
+ subject
304
+ })),
305
+ onMessageDelete: (thread, messageId) => dispatch(createIntent(ThreadAction.DeleteMessage, {
306
+ thread,
307
+ subject,
308
+ messageId
309
+ })),
310
+ onThreadToggleResolved: (thread) => dispatch(createIntent(ThreadAction.ToggleResolved, {
311
+ thread
312
+ })),
313
+ onComment: (thread) => dispatch(createIntent(ThreadAction.OnMessageAdd, {
314
+ thread,
315
+ subject
316
+ }))
343
317
  });
344
318
  };
345
319
 
@@ -358,20 +332,22 @@ var ThreadSettings = ({ settings }) => {
358
332
  };
359
333
 
360
334
  // packages/plugins/plugin-thread/src/components/index.ts
361
- var ThreadMain = lazy(() => import("./ThreadMain-4IAS67KE.mjs"));
362
- var ThreadArticle = lazy(() => import("./ThreadArticle-6IXTL7CH.mjs"));
335
+ var ThreadMain = lazy(() => import("./ThreadMain-ABEDFWHC.mjs"));
336
+ var ThreadArticle = lazy(() => import("./ThreadArticle-EWLTNU6Z.mjs"));
363
337
 
364
338
  // packages/plugins/plugin-thread/src/extensions/threads.ts
365
339
  import { EditorView } from "@codemirror/view";
366
340
  import { computed, effect } from "@preact/signals-core";
341
+ import { createIntent as createIntent2 } from "@dxos/app-framework";
342
+ import { Ref } from "@dxos/echo-schema";
343
+ import { RefArray as RefArray3 } from "@dxos/live-object";
367
344
  import { ThreadType } from "@dxos/plugin-space/types";
368
345
  import { getSpace as getSpace2, getTextInRange, createDocAccessor, fullyQualifiedId as fullyQualifiedId4 } from "@dxos/react-client/echo";
369
346
  import { comments, createExternalCommentSync } from "@dxos/react-ui-editor";
370
- import { nonNullable as nonNullable3 } from "@dxos/util";
371
347
  var getName = (doc, anchor) => {
372
348
  if (doc.content) {
373
349
  const [start, end] = anchor.split(":");
374
- return getTextInRange(createDocAccessor(doc.content, [
350
+ return getTextInRange(createDocAccessor(doc.content.target, [
375
351
  "content"
376
352
  ]), start, end);
377
353
  }
@@ -384,14 +360,14 @@ var threads = (state, doc, dispatch) => {
384
360
  ];
385
361
  }
386
362
  const threads2 = computed(() => [
387
- ...doc.threads.filter(nonNullable3),
363
+ ...RefArray3.allResolvedTargets(doc.threads),
388
364
  ...state.drafts[fullyQualifiedId4(doc)] ?? []
389
365
  ].filter((thread) => !(thread?.status === "resolved")));
390
366
  return [
391
367
  EditorView.updateListener.of((update) => {
392
368
  if (update.docChanged) {
393
- doc.threads.forEach((thread) => {
394
- if (thread?.anchor) {
369
+ RefArray3.allResolvedTargets(doc.threads).forEach((thread) => {
370
+ if (thread.anchor) {
395
371
  const name = getName(doc, thread.anchor);
396
372
  if (name && name !== thread.name) {
397
373
  thread.name = name;
@@ -408,14 +384,11 @@ var threads = (state, doc, dispatch) => {
408
384
  id: fullyQualifiedId4(doc),
409
385
  onCreate: ({ cursor }) => {
410
386
  const name = getName(doc, cursor);
411
- void dispatch({
412
- action: ThreadAction.CREATE,
413
- data: {
414
- cursor,
415
- name,
416
- subject: doc
417
- }
418
- });
387
+ void dispatch(createIntent2(ThreadAction.Create, {
388
+ cursor,
389
+ name,
390
+ subject: doc
391
+ }));
419
392
  },
420
393
  onDelete: ({ id }) => {
421
394
  const draft = state.drafts[fullyQualifiedId4(doc)];
@@ -425,26 +398,26 @@ var threads = (state, doc, dispatch) => {
425
398
  draft.splice(index, 1);
426
399
  }
427
400
  }
428
- const thread = doc.threads.find((thread2) => thread2?.id === id);
401
+ const thread = doc.threads.find(Ref.hasObjectId(id))?.target;
429
402
  if (thread) {
430
403
  thread.anchor = void 0;
431
404
  }
432
405
  },
433
406
  onUpdate: ({ id, cursor }) => {
434
- const thread = state.drafts[fullyQualifiedId4(doc)]?.find((thread2) => fullyQualifiedId4(thread2) === id) ?? doc.threads.find((thread2) => thread2?.id === id);
407
+ const thread = state.drafts[fullyQualifiedId4(doc)]?.find((thread2) => fullyQualifiedId4(thread2) === id) ?? doc.threads.find(Ref.hasObjectId(id))?.target;
435
408
  if (thread instanceof ThreadType && thread.anchor) {
436
409
  thread.name = getName(doc, thread.anchor);
437
410
  thread.anchor = cursor;
438
411
  }
439
412
  },
440
- onSelect: ({ selection: { current, closest } }) => {
441
- void dispatch({
442
- action: ThreadAction.SELECT,
443
- data: {
444
- current: current ?? closest,
413
+ onSelect: ({ selection }) => {
414
+ const current = selection.current ?? selection.closest;
415
+ if (current) {
416
+ void dispatch(createIntent2(ThreadAction.Select, {
417
+ current,
445
418
  skipOpen: true
446
- }
447
- });
419
+ }));
420
+ }
448
421
  }
449
422
  })
450
423
  ];
@@ -510,7 +483,6 @@ var ThreadPlugin = () => {
510
483
  }
511
484
  return viewStore[subjectId];
512
485
  };
513
- let navigationPlugin;
514
486
  let intentPlugin;
515
487
  const unsubscribeCallbacks = [];
516
488
  return {
@@ -537,8 +509,7 @@ var ThreadPlugin = () => {
537
509
  }
538
510
  };
539
511
  },
540
- ready: async (plugins) => {
541
- navigationPlugin = resolvePlugin(plugins, parseNavigationPlugin);
512
+ ready: async ({ plugins }) => {
542
513
  intentPlugin = resolvePlugin(plugins, parseIntentPlugin);
543
514
  },
544
515
  unload: async () => {
@@ -549,7 +520,7 @@ var ThreadPlugin = () => {
549
520
  metadata: {
550
521
  records: {
551
522
  [ChannelType2.typename]: {
552
- createObject: ThreadAction.CREATE,
523
+ createObject: (props) => createIntent3(ThreadAction.Create, props),
553
524
  placeholder: [
554
525
  "channel name placeholder",
555
526
  {
@@ -558,11 +529,11 @@ var ThreadPlugin = () => {
558
529
  ],
559
530
  icon: "ph--chat--regular",
560
531
  // TODO(wittjosiah): Move out of metadata.
561
- loadReferences: (channel) => loadObjectReferences(channel, (channel2) => channel2.threads)
532
+ loadReferences: async (channel) => await RefArray4.loadAll(channel.threads ?? [])
562
533
  },
563
534
  [ThreadType2.typename]: {
564
535
  // TODO(wittjosiah): Move out of metadata.
565
- loadReferences: (thread) => loadObjectReferences(thread, (thread2) => thread2.messages)
536
+ loadReferences: async (thread) => await RefArray4.loadAll(thread.messages ?? [])
566
537
  },
567
538
  [MessageType2.typename]: {
568
539
  // TODO(wittjosiah): Move out of metadata.
@@ -610,7 +581,7 @@ var ThreadPlugin = () => {
610
581
  graph: {
611
582
  builder: (plugins) => {
612
583
  const client = resolvePlugin(plugins, parseClientPlugin)?.provides.client;
613
- const dispatch = resolvePlugin(plugins, parseIntentPlugin)?.provides.intent.dispatch;
584
+ const dispatch = resolvePlugin(plugins, parseIntentPlugin)?.provides.intent.dispatchPromise;
614
585
  const metadataResolver = resolvePlugin(plugins, parseMetadataResolverPlugin)?.provides.metadata.resolver;
615
586
  if (!client || !dispatch || !metadataResolver) {
616
587
  return [];
@@ -680,20 +651,17 @@ var ThreadPlugin = () => {
680
651
  }
681
652
  const [spaceId, objectId] = dataId.split(":");
682
653
  const viewState = getViewState(dataId);
683
- const toggle = () => {
654
+ const toggle = async () => {
684
655
  const newToggleState = !viewState.showResolvedThreads;
685
656
  viewState.showResolvedThreads = newToggleState;
686
- void dispatch({
687
- action: ObservabilityAction.SEND_EVENT,
688
- data: {
689
- name: "threads.toggle-show-resolved",
690
- properties: {
691
- spaceId,
692
- threadId: objectId,
693
- showResolved: newToggleState
694
- }
657
+ await dispatch(createIntent3(ObservabilityAction.SendEvent, {
658
+ name: "threads.toggle-show-resolved",
659
+ properties: {
660
+ spaceId,
661
+ threadId: objectId,
662
+ showResolved: newToggleState
695
663
  }
696
- });
664
+ }));
697
665
  };
698
666
  return [
699
667
  {
@@ -714,440 +682,315 @@ var ThreadPlugin = () => {
714
682
  }
715
683
  ];
716
684
  }
717
- }),
718
- createExtension({
719
- id: ThreadAction.CREATE,
720
- filter: (node) => !!settings.values.standalone && isActionGroup(node) && node.id.startsWith(SpaceAction.ADD_OBJECT),
721
- actions: ({ node }) => {
722
- const id = node.id.split("/").at(-1);
723
- const [spaceId, objectId] = id?.split(":") ?? [];
724
- const space = client.spaces.get().find((space2) => space2.id === spaceId);
725
- const object = objectId && space?.db.getObjectById(objectId);
726
- const target = objectId ? object : space;
727
- if (!target) {
728
- return;
729
- }
730
- return [
731
- {
732
- id: `${THREAD_PLUGIN}/create/${node.id}`,
733
- data: async () => {
734
- await dispatch([
735
- {
736
- plugin: THREAD_PLUGIN,
737
- action: ThreadAction.CREATE
738
- },
739
- {
740
- action: SpaceAction.ADD_OBJECT,
741
- data: {
742
- target
743
- }
744
- },
745
- {
746
- action: NavigationAction.OPEN
747
- }
748
- ]);
749
- },
750
- properties: {
751
- label: [
752
- "create channel label",
753
- {
754
- ns: THREAD_PLUGIN
755
- }
756
- ],
757
- icon: "ph--chat--regular",
758
- testId: "threadPlugin.createObject"
759
- }
760
- }
761
- ];
762
- }
763
685
  })
764
686
  ];
765
687
  }
766
688
  },
767
689
  surface: {
768
- component: ({ data, role }) => {
769
- switch (role) {
770
- case "main": {
771
- return data.active instanceof ChannelType2 && data.active.threads[0] ? /* @__PURE__ */ React5.createElement(ThreadMain, {
772
- thread: data.active.threads[0]
773
- }) : null;
774
- }
775
- case "settings": {
776
- return data.plugin === meta_default.id ? /* @__PURE__ */ React5.createElement(ThreadSettings, {
777
- settings: settings.values
778
- }) : null;
779
- }
780
- case "article": {
781
- const location = navigationPlugin?.provides.location;
782
- if (data.object instanceof ChannelType2 && data.object.threads[0]) {
783
- const channel = data.object;
690
+ definitions: ({ plugins }) => {
691
+ const location = resolvePlugin(plugins, parseNavigationPlugin)?.provides.location;
692
+ return [
693
+ createSurface({
694
+ id: `${THREAD_PLUGIN}/channel`,
695
+ role: "article",
696
+ filter: (data) => data.subject instanceof ChannelType2 && !!data.subject.threads[0],
697
+ component: ({ data }) => {
698
+ const channel = data.subject;
699
+ const thread = channel.threads[0].target;
784
700
  if (isLayoutParts(location?.active) && location.active.main) {
785
701
  const layoutEntries = location.active.main;
786
702
  const currentPosition = layoutEntries.findIndex((entry) => channel.id === entry.id);
787
703
  if (currentPosition > 0) {
788
704
  const objectToTheLeft = layoutEntries[currentPosition - 1];
789
- const context = getSpace3(data.object)?.db.getObjectById(objectToTheLeft.id);
705
+ const context = getSpace3(channel)?.db.getObjectById(objectToTheLeft.id);
790
706
  return /* @__PURE__ */ React5.createElement(ThreadArticle, {
791
- thread: data.object.threads[0],
707
+ thread,
792
708
  context
793
709
  });
794
710
  }
795
711
  }
796
712
  return /* @__PURE__ */ React5.createElement(ThreadArticle, {
797
- thread: data.object.threads[0]
713
+ thread
798
714
  });
799
715
  }
800
- if (data.subject instanceof ThreadType2) {
801
- return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(ChatHeading, {
802
- attendableId: data.subject.id
803
- }), /* @__PURE__ */ React5.createElement(ChatContainer, {
804
- thread: data.subject
805
- }));
806
- }
807
- break;
808
- }
809
- case "complementary--comments": {
810
- if (data.subject && typeof data.subject === "object" && "threads" in data.subject && Array.isArray(data.subject.threads) && !(data.subject instanceof ChannelType2)) {
716
+ }),
717
+ createSurface({
718
+ id: `${THREAD_PLUGIN}/thread`,
719
+ role: "complementary--comments",
720
+ filter: (data) => !!data.subject && typeof data.subject === "object" && "threads" in data.subject && Array.isArray(data.subject.threads) && !(data.subject instanceof ChannelType2),
721
+ component: ({ data }) => {
811
722
  const { showResolvedThreads } = getViewState(fullyQualifiedId5(data.subject));
812
723
  return /* @__PURE__ */ React5.createElement(ThreadComplementary, {
813
- role,
814
724
  subject: data.subject,
815
725
  drafts: state.drafts[fullyQualifiedId5(data.subject)],
816
726
  current: state.current,
817
727
  showResolvedThreads
818
728
  });
819
729
  }
820
- break;
821
- }
822
- }
823
- return null;
730
+ }),
731
+ createSurface({
732
+ id: `${THREAD_PLUGIN}/settings`,
733
+ role: "settings",
734
+ filter: (data) => data.plugin === THREAD_PLUGIN,
735
+ component: () => /* @__PURE__ */ React5.createElement(ThreadSettings, {
736
+ settings: settings.values
737
+ })
738
+ })
739
+ ];
824
740
  }
825
741
  },
826
742
  intent: {
827
- resolver: async (intent) => {
828
- switch (intent.action) {
829
- case ThreadAction.CREATE: {
830
- if (intent.data && intent.data.cursor !== void 0) {
831
- const { cursor, name, subject } = intent.data;
832
- if (subject?.threads === void 0) {
833
- try {
834
- subject.threads = [];
835
- } catch (err) {
836
- log.error("Subject does not support threads array", subject?.typename, {
837
- F: __dxlog_file,
838
- L: 371,
839
- S: void 0,
840
- C: (f, a) => f(...a)
841
- });
842
- return;
843
- }
844
- }
845
- const subjectId = fullyQualifiedId5(subject);
846
- const thread = create2(ThreadType2, {
847
- name,
848
- anchor: cursor,
849
- messages: [],
850
- status: "staged"
851
- });
852
- const draft = state.drafts[subjectId];
853
- if (draft) {
854
- draft.push(thread);
855
- } else {
856
- state.drafts[subjectId] = [
857
- thread
858
- ];
743
+ resolvers: () => [
744
+ createResolver(ThreadAction.Create, ({ name, cursor, subject }) => {
745
+ if (cursor && subject) {
746
+ if (subject?.threads === void 0) {
747
+ try {
748
+ subject.threads = [];
749
+ } catch (err) {
750
+ log.error("Subject does not support threads array", subject?.typename, {
751
+ F: __dxlog_file,
752
+ L: 314,
753
+ S: void 0,
754
+ C: (f, a) => f(...a)
755
+ });
756
+ return;
859
757
  }
860
- return {
861
- data: thread,
862
- intents: [
863
- [
864
- {
865
- action: ThreadAction.SELECT,
866
- data: {
867
- current: fullyQualifiedId5(thread)
868
- }
869
- }
870
- ],
871
- [
872
- {
873
- action: NavigationAction.OPEN,
874
- data: {
875
- activeParts: {
876
- complementary: "comments"
877
- }
878
- }
879
- }
880
- ],
881
- [
882
- {
883
- action: LayoutAction2.SET_LAYOUT,
884
- data: {
885
- element: "complementary",
886
- state: true
887
- }
888
- }
889
- ]
890
- ]
891
- };
758
+ }
759
+ const subjectId = fullyQualifiedId5(subject);
760
+ const thread = create2(ThreadType2, {
761
+ name,
762
+ anchor: cursor,
763
+ messages: [],
764
+ status: "staged"
765
+ });
766
+ const draft = state.drafts[subjectId];
767
+ if (draft) {
768
+ draft.push(thread);
892
769
  } else {
893
- return {
894
- data: create2(ChannelType2, {
770
+ state.drafts[subjectId] = [
771
+ thread
772
+ ];
773
+ }
774
+ return {
775
+ data: {
776
+ object: thread
777
+ },
778
+ intents: [
779
+ createIntent3(ThreadAction.Select, {
780
+ current: fullyQualifiedId5(thread)
781
+ }),
782
+ createIntent3(NavigationAction.Open, {
783
+ activeParts: {
784
+ complementary: "comments"
785
+ }
786
+ }),
787
+ createIntent3(LayoutAction2.SetLayout, {
788
+ element: "complementary",
789
+ state: true
790
+ })
791
+ ]
792
+ };
793
+ } else {
794
+ return {
795
+ data: {
796
+ object: create2(ChannelType2, {
895
797
  threads: [
896
- create2(ThreadType2, {
798
+ makeRef2(create2(ThreadType2, {
897
799
  messages: []
898
- })
800
+ }))
899
801
  ]
900
802
  })
901
- };
803
+ }
804
+ };
805
+ }
806
+ }),
807
+ createResolver(ThreadAction.Select, ({ current, skipOpen }) => {
808
+ state.current = current;
809
+ return {
810
+ intents: !skipOpen ? [
811
+ createIntent3(NavigationAction.Open, {
812
+ activeParts: {
813
+ complementary: "comments"
814
+ }
815
+ })
816
+ ] : void 0
817
+ };
818
+ }),
819
+ createResolver(ThreadAction.ToggleResolved, ({ thread }) => {
820
+ if (thread.status === "active" || thread.status === void 0) {
821
+ thread.status = "resolved";
822
+ } else if (thread.status === "resolved") {
823
+ thread.status = "active";
824
+ }
825
+ const space = getSpace3(thread);
826
+ const spaceId = space?.id;
827
+ return {
828
+ intents: [
829
+ createIntent3(ObservabilityAction.SendEvent, {
830
+ name: "threads.toggle-resolved",
831
+ properties: {
832
+ threadId: thread.id,
833
+ spaceId
834
+ }
835
+ })
836
+ ]
837
+ };
838
+ }),
839
+ createResolver(ThreadAction.Delete, ({ subject, thread }, undo) => {
840
+ const subjectId = fullyQualifiedId5(subject);
841
+ const draft = state.drafts[subjectId];
842
+ if (draft) {
843
+ const index = draft.findIndex((t) => t.id === thread.id);
844
+ if (index !== -1) {
845
+ draft.splice(index, 1);
846
+ return;
902
847
  }
903
848
  }
904
- case ThreadAction.SELECT: {
905
- state.current = intent.data?.current;
849
+ const space = getSpace3(thread);
850
+ if (!space || !subject.threads) {
851
+ return;
852
+ }
853
+ if (!undo) {
854
+ const index = subject.threads.findIndex((t) => t?.id === thread.id);
855
+ const cursor = subject.threads[index]?.anchor;
856
+ if (index !== -1) {
857
+ subject.threads?.splice(index, 1);
858
+ }
859
+ space.db.remove(thread);
906
860
  return {
907
- data: true,
908
- intents: !intent.data?.skipOpen ? [
909
- [
861
+ undoable: {
862
+ message: [
863
+ "thread deleted label",
910
864
  {
911
- action: NavigationAction.OPEN,
912
- data: {
913
- activeParts: {
914
- complementary: "comments"
915
- }
916
- }
865
+ ns: THREAD_PLUGIN
917
866
  }
918
- ]
919
- ] : []
867
+ ],
868
+ data: {
869
+ cursor
870
+ }
871
+ },
872
+ intents: [
873
+ createIntent3(ObservabilityAction.SendEvent, {
874
+ name: "threads.delete",
875
+ properties: {
876
+ threadId: thread.id,
877
+ spaceId: space.id
878
+ }
879
+ })
880
+ ]
920
881
  };
921
- }
922
- case ThreadAction.TOGGLE_RESOLVED: {
923
- const { thread } = intent.data ?? {};
924
- if (!(thread instanceof ThreadType2)) {
925
- return;
926
- }
927
- if (thread.status === "active" || thread.status === void 0) {
928
- thread.status = "resolved";
929
- } else if (thread.status === "resolved") {
930
- thread.status = "active";
931
- }
932
- const space = getSpace3(thread);
933
- const spaceId = space?.id;
882
+ } else {
883
+ const savedThread = space.db.add(thread);
884
+ subject.threads.push(savedThread);
934
885
  return {
935
- data: true,
936
886
  intents: [
937
- [
938
- {
939
- action: ObservabilityAction.SEND_EVENT,
940
- data: {
941
- name: "threads.toggle-resolved",
942
- properties: {
943
- threadId: thread.id,
944
- spaceId
945
- }
946
- }
887
+ createIntent3(ObservabilityAction.SendEvent, {
888
+ name: "threads.undo-delete",
889
+ properties: {
890
+ threadId: thread.id,
891
+ spaceId: space.id
947
892
  }
948
- ]
893
+ })
949
894
  ]
950
895
  };
951
896
  }
952
- case ThreadAction.DELETE: {
953
- const { subject, thread } = intent.data ?? {};
954
- if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject)) {
955
- return;
956
- }
957
- const subjectId = fullyQualifiedId5(subject);
958
- const draft = state.drafts[subjectId];
959
- if (draft) {
960
- const index = draft.findIndex((t) => t.id === thread.id);
961
- if (index !== -1) {
962
- draft.splice(index, 1);
963
- return {
964
- data: true
965
- };
966
- }
897
+ }),
898
+ createResolver(ThreadAction.OnMessageAdd, ({ thread, subject }) => {
899
+ const subjectId = fullyQualifiedId5(subject);
900
+ const space = getSpace3(subject);
901
+ const intents = [];
902
+ const analyticsProperties = {
903
+ threadId: thread.id,
904
+ spaceId: space?.id
905
+ };
906
+ if (state.drafts[subjectId]?.find((t) => t === thread)) {
907
+ thread.status = "active";
908
+ subject.threads ? subject.threads.push(makeRef2(thread)) : subject.threads = [
909
+ makeRef2(thread)
910
+ ];
911
+ state.drafts[subjectId] = state.drafts[subjectId]?.filter(({ id }) => id !== thread.id);
912
+ intents.push(createIntent3(ObservabilityAction.SendEvent, {
913
+ name: "threads.thread-created",
914
+ properties: analyticsProperties
915
+ }));
916
+ }
917
+ intents.push(createIntent3(ObservabilityAction.SendEvent, {
918
+ name: "threads.message-added",
919
+ properties: {
920
+ ...analyticsProperties,
921
+ threadLength: thread.messages.length
967
922
  }
968
- const space = getSpace3(thread);
969
- if (!space || !subject.threads) {
923
+ }));
924
+ return {
925
+ intents
926
+ };
927
+ }),
928
+ createResolver(ThreadAction.DeleteMessage, ({ subject, thread, messageId, message, messageIndex }, undo) => {
929
+ const space = getSpace3(subject);
930
+ if (!undo) {
931
+ const messageIndex2 = thread.messages.findIndex(Ref2.hasObjectId(messageId));
932
+ const message2 = thread.messages[messageIndex2]?.target;
933
+ if (!message2) {
970
934
  return;
971
935
  }
972
- if (!intent.undo) {
973
- const index = subject.threads.findIndex((t) => t?.id === thread.id);
974
- const cursor = subject.threads[index]?.anchor;
975
- if (index !== -1) {
976
- subject.threads?.splice(index, 1);
977
- }
978
- space.db.remove(thread);
979
- return {
980
- undoable: {
981
- message: translations_default[0]["en-US"][THREAD_PLUGIN]["thread deleted label"],
982
- data: {
983
- cursor
984
- }
985
- },
986
- intents: [
987
- [
988
- {
989
- action: ObservabilityAction.SEND_EVENT,
990
- data: {
991
- name: "threads.delete",
992
- properties: {
993
- threadId: thread.id,
994
- spaceId: space.id
995
- }
996
- }
997
- }
998
- ]
999
- ]
1000
- };
1001
- } else if (intent.undo) {
1002
- const savedThread = space.db.add(thread);
1003
- subject.threads.push(savedThread);
936
+ if (messageIndex2 === 0 && thread.messages.length === 1) {
1004
937
  return {
1005
- data: true,
1006
938
  intents: [
1007
- [
1008
- {
1009
- action: ObservabilityAction.SEND_EVENT,
1010
- data: {
1011
- name: "threads.undo-delete",
1012
- properties: {
1013
- threadId: thread.id,
1014
- spaceId: space.id
1015
- }
1016
- }
1017
- }
1018
- ]
939
+ createIntent3(ThreadAction.Delete, {
940
+ subject,
941
+ thread
942
+ })
1019
943
  ]
1020
944
  };
945
+ } else {
946
+ thread.messages.splice(messageIndex2, 1);
1021
947
  }
1022
- break;
1023
- }
1024
- case ThreadAction.ON_MESSAGE_ADD: {
1025
- const { thread, subject } = intent.data ?? {};
1026
- if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject && Array.isArray(subject.threads))) {
1027
- return;
1028
- }
1029
- const subjectId = fullyQualifiedId5(subject);
1030
- const space = getSpace3(subject);
1031
- const intents = [];
1032
- const analyticsProperties = {
1033
- threadId: thread.id,
1034
- spaceId: space?.id
1035
- };
1036
- if (state.drafts[subjectId]?.find((t) => t === thread)) {
1037
- thread.status = "active";
1038
- subject.threads ? subject.threads.push(thread) : subject.threads = [
1039
- thread
1040
- ];
1041
- state.drafts[subjectId] = state.drafts[subjectId]?.filter(({ id }) => id !== thread.id);
1042
- intents.push({
1043
- action: ObservabilityAction.SEND_EVENT,
948
+ return {
949
+ undoable: {
950
+ message: [
951
+ "message deleted label",
952
+ {
953
+ ns: THREAD_PLUGIN
954
+ }
955
+ ],
1044
956
  data: {
1045
- name: "threads.thread-created",
1046
- properties: analyticsProperties
1047
- }
1048
- });
1049
- }
1050
- intents.push({
1051
- action: ObservabilityAction.SEND_EVENT,
1052
- data: {
1053
- name: "threads.message-added",
1054
- properties: {
1055
- ...analyticsProperties,
1056
- threadLength: thread.messages.length
957
+ message: message2,
958
+ messageIndex: messageIndex2
1057
959
  }
1058
- }
1059
- });
1060
- return {
1061
- data: thread,
960
+ },
1062
961
  intents: [
1063
- intents
962
+ createIntent3(ObservabilityAction.SendEvent, {
963
+ name: "threads.message.delete",
964
+ properties: {
965
+ threadId: thread.id,
966
+ spaceId: space?.id
967
+ }
968
+ })
1064
969
  ]
1065
970
  };
1066
- }
1067
- case ThreadAction.DELETE_MESSAGE: {
1068
- const { subject, thread, messageId } = intent.data ?? {};
1069
- const space = getSpace3(subject);
1070
- if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject)) {
971
+ } else {
972
+ if (!messageIndex || !message) {
1071
973
  return;
1072
974
  }
1073
- if (!intent.undo) {
1074
- const message = thread.messages.find((m) => m?.id === messageId);
1075
- const messageIndex = thread.messages.findIndex((m) => m?.id === messageId);
1076
- if (messageIndex === -1 || !message) {
1077
- return void 0;
1078
- }
1079
- if (messageIndex === 0 && thread.messages.length === 1) {
1080
- return {
1081
- intents: [
1082
- [
1083
- {
1084
- action: ThreadAction.DELETE,
1085
- data: {
1086
- subject,
1087
- thread
1088
- }
1089
- }
1090
- ]
1091
- ]
1092
- };
1093
- } else {
1094
- thread.messages.splice(messageIndex, 1);
1095
- }
1096
- return {
1097
- undoable: {
1098
- message: translations_default[0]["en-US"][THREAD_PLUGIN]["message deleted label"],
1099
- data: {
1100
- message,
1101
- messageIndex
975
+ thread.messages.splice(messageIndex, 0, makeRef2(message));
976
+ return {
977
+ intents: [
978
+ createIntent3(ObservabilityAction.SendEvent, {
979
+ name: "threads.message.undo-delete",
980
+ properties: {
981
+ threadId: thread.id,
982
+ spaceId: space?.id
1102
983
  }
1103
- },
1104
- intents: [
1105
- [
1106
- {
1107
- action: ObservabilityAction.SEND_EVENT,
1108
- data: {
1109
- name: "threads.message.delete",
1110
- properties: {
1111
- threadId: thread.id,
1112
- spaceId: space?.id
1113
- }
1114
- }
1115
- }
1116
- ]
1117
- ]
1118
- };
1119
- } else if (intent.undo) {
1120
- const message = intent.data?.message;
1121
- const messageIndex = intent.data?.messageIndex;
1122
- if (!(message instanceof MessageType2) || !(typeof messageIndex === "number")) {
1123
- return;
1124
- }
1125
- thread.messages.splice(messageIndex, 0, message);
1126
- return {
1127
- data: true,
1128
- intents: [
1129
- [
1130
- {
1131
- action: ObservabilityAction.SEND_EVENT,
1132
- data: {
1133
- name: "threads.message.undo-delete",
1134
- properties: {
1135
- threadId: thread.id,
1136
- spaceId: space?.id
1137
- }
1138
- }
1139
- }
1140
- ]
1141
- ]
1142
- };
1143
- }
984
+ })
985
+ ]
986
+ };
1144
987
  }
1145
- }
1146
- }
988
+ })
989
+ ]
1147
990
  },
1148
991
  markdown: {
1149
992
  extensions: ({ document: doc }) => {
1150
- return threads(state, doc, intentPlugin?.provides.intent.dispatch);
993
+ return threads(state, doc, intentPlugin?.provides.intent.dispatchPromise);
1151
994
  }
1152
995
  }
1153
996
  }