@dxos/plugin-thread 0.6.13-staging.1e988a3 → 0.6.14-main.1366248
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-6RFOFTU2.mjs} +3 -3
- package/dist/lib/browser/{ThreadMain-ZDCRC6RG.mjs → ThreadMain-45OFO3G6.mjs} +3 -3
- package/dist/lib/browser/{chunk-P7ZE5N5M.mjs → chunk-OTCR7JTS.mjs} +17 -17
- package/dist/lib/browser/chunk-OTCR7JTS.mjs.map +7 -0
- package/dist/lib/browser/chunk-YLYCGZ62.mjs +17 -0
- package/dist/lib/browser/chunk-YLYCGZ62.mjs.map +7 -0
- package/dist/lib/browser/{chunk-GKPZHUT3.mjs → chunk-YQUONHZJ.mjs} +2 -2
- package/dist/lib/browser/chunk-YQUONHZJ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +452 -388
- 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-IUK2EECC.cjs} +7 -7
- package/dist/lib/node/{ThreadMain-XJX75GHG.cjs → ThreadMain-CXIQPH4H.cjs} +7 -7
- package/dist/lib/node/{chunk-D5GOVXHS.cjs → chunk-LGA276VA.cjs} +6 -6
- package/dist/lib/node/chunk-LGA276VA.cjs.map +7 -0
- package/dist/lib/node/{chunk-5PZNPPQF.cjs → chunk-XOW5SL5M.cjs} +66 -66
- package/dist/lib/node/chunk-XOW5SL5M.cjs.map +7 -0
- package/dist/lib/node/{chunk-BWBONZGU.cjs → chunk-YWFYN3OY.cjs} +8 -22
- package/dist/lib/node/chunk-YWFYN3OY.cjs.map +7 -0
- package/dist/lib/node/index.cjs +501 -441
- 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-OA3T4XFJ.mjs +19 -0
- package/dist/lib/node-esm/ThreadArticle-OA3T4XFJ.mjs.map +7 -0
- package/dist/lib/node-esm/ThreadMain-VXFO6JL6.mjs +27 -0
- package/dist/lib/node-esm/ThreadMain-VXFO6JL6.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-3CZBPOEH.mjs +21 -0
- package/dist/lib/node-esm/chunk-3CZBPOEH.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-5R5QKQY4.mjs +411 -0
- package/dist/lib/node-esm/chunk-5R5QKQY4.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-SSEJYCYQ.mjs +19 -0
- package/dist/lib/node-esm/chunk-SSEJYCYQ.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1167 -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/Chat.stories.d.ts +3 -42
- package/dist/types/src/components/Chat.stories.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/Comments.stories.d.ts +3 -41
- package/dist/types/src/components/Comments.stories.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/index.d.ts +6 -6
- package/dist/types/src/components/index.d.ts.map +1 -1
- 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/components/types.d.ts +2 -2
- package/dist/types/src/components/types.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 +4 -9
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +1 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +8 -2
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +42 -46
- package/src/ThreadPlugin.tsx +158 -309
- package/src/components/Chat.stories.tsx +7 -4
- package/src/components/ChatContainer.tsx +7 -8
- package/src/components/CommentContainer.tsx +25 -23
- package/src/components/Comments.stories.tsx +9 -6
- package/src/components/CommentsContainer.tsx +18 -31
- package/src/components/MessageContainer.tsx +15 -24
- package/src/components/ThreadComplementary.tsx +113 -0
- package/src/components/ThreadSettings.tsx +3 -3
- package/src/components/index.ts +6 -6
- package/src/components/types.ts +2 -2
- package/src/extensions/index.ts +5 -0
- package/src/extensions/threads.ts +117 -0
- package/src/meta.ts +16 -0
- package/src/translations.ts +1 -0
- package/src/types.ts +11 -4
- package/dist/lib/browser/chunk-5IBJO53M.mjs +0 -21
- package/dist/lib/browser/chunk-5IBJO53M.mjs.map +0 -7
- package/dist/lib/browser/chunk-GKPZHUT3.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/lib/node/chunk-D5GOVXHS.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-6RFOFTU2.mjs.map} +0 -0
- /package/dist/lib/browser/{ThreadMain-ZDCRC6RG.mjs.map → ThreadMain-45OFO3G6.mjs.map} +0 -0
- /package/dist/lib/node/{ThreadArticle-DO56JXBU.cjs.map → ThreadArticle-IUK2EECC.cjs.map} +0 -0
- /package/dist/lib/node/{ThreadMain-XJX75GHG.cjs.map → ThreadMain-CXIQPH4H.cjs.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ThreadAction
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YQUONHZJ.mjs";
|
|
4
4
|
import {
|
|
5
5
|
ChatContainer,
|
|
6
6
|
ChatHeading,
|
|
@@ -10,120 +10,98 @@ import {
|
|
|
10
10
|
useAnalyticsCallback,
|
|
11
11
|
useOnEditAnalytics,
|
|
12
12
|
useStatus
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-OTCR7JTS.mjs";
|
|
14
14
|
import {
|
|
15
15
|
THREAD_ITEM,
|
|
16
16
|
THREAD_PLUGIN,
|
|
17
17
|
meta_default
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-YLYCGZ62.mjs";
|
|
19
19
|
|
|
20
20
|
// packages/plugins/plugin-thread/src/ThreadPlugin.tsx
|
|
21
|
-
import { Chat } from "@phosphor-icons/react";
|
|
22
|
-
import { computed, effect } from "@preact/signals-core";
|
|
23
21
|
import React5 from "react";
|
|
24
|
-
import {
|
|
25
|
-
import { getTypename } from "@dxos/echo-schema";
|
|
26
|
-
import { create as create2 } from "@dxos/echo-schema";
|
|
22
|
+
import { NavigationAction, isLayoutParts, parseIntentPlugin, parseNavigationPlugin, parseMetadataResolverPlugin, resolvePlugin, LayoutAction as LayoutAction2 } from "@dxos/app-framework";
|
|
27
23
|
import { LocalStorageStore } from "@dxos/local-storage";
|
|
28
|
-
import {
|
|
24
|
+
import { log } from "@dxos/log";
|
|
29
25
|
import { parseClientPlugin } from "@dxos/plugin-client";
|
|
30
|
-
import { createExtension, isActionGroup } from "@dxos/plugin-graph";
|
|
31
|
-
import { DocumentType } from "@dxos/plugin-markdown/types";
|
|
26
|
+
import { createExtension, isActionGroup, toSignal } from "@dxos/plugin-graph";
|
|
32
27
|
import { ObservabilityAction } from "@dxos/plugin-observability/meta";
|
|
33
28
|
import { SpaceAction } from "@dxos/plugin-space";
|
|
34
|
-
import { ThreadType, MessageType as MessageType2, ChannelType } from "@dxos/plugin-space/types";
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import { createAttendableAttributes } from "@dxos/react-ui-attention";
|
|
38
|
-
import { comments, createExternalCommentSync, listener as listener2 } from "@dxos/react-ui-editor";
|
|
29
|
+
import { ThreadType as ThreadType2, MessageType as MessageType2, ChannelType } from "@dxos/plugin-space/types";
|
|
30
|
+
import { create as create2, getTypename } from "@dxos/react-client/echo";
|
|
31
|
+
import { getSpace as getSpace3, fullyQualifiedId as fullyQualifiedId5, loadObjectReferences, parseId } from "@dxos/react-client/echo";
|
|
39
32
|
import { translations as threadTranslations } from "@dxos/react-ui-thread";
|
|
40
|
-
import { nonNullable as nonNullable2 } from "@dxos/util";
|
|
41
33
|
|
|
42
34
|
// packages/plugins/plugin-thread/src/components/index.ts
|
|
43
|
-
import
|
|
44
|
-
|
|
45
|
-
// packages/plugins/plugin-thread/src/components/ThreadSettings.tsx
|
|
46
|
-
import React from "react";
|
|
47
|
-
import { SettingsValue } from "@dxos/plugin-settings";
|
|
48
|
-
import { Input, useTranslation } from "@dxos/react-ui";
|
|
49
|
-
var ThreadSettings = ({ settings }) => {
|
|
50
|
-
const { t } = useTranslation(THREAD_PLUGIN);
|
|
51
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(SettingsValue, {
|
|
52
|
-
label: t("settings standalone label")
|
|
53
|
-
}, /* @__PURE__ */ React.createElement(Input.Switch, {
|
|
54
|
-
checked: settings.standalone,
|
|
55
|
-
onCheckedChange: (checked) => settings.standalone = !!checked
|
|
56
|
-
})));
|
|
57
|
-
};
|
|
35
|
+
import { lazy } from "react";
|
|
58
36
|
|
|
59
37
|
// packages/plugins/plugin-thread/src/components/CommentContainer.tsx
|
|
60
38
|
import { CheckCircle, X } from "@phosphor-icons/react";
|
|
61
|
-
import
|
|
39
|
+
import React, { useCallback, useMemo, useRef, useState } from "react";
|
|
62
40
|
import { create } from "@dxos/echo-schema";
|
|
63
41
|
import { MessageType } from "@dxos/plugin-space/types";
|
|
64
|
-
import { getSpace, useMembers } from "@dxos/react-client/echo";
|
|
42
|
+
import { fullyQualifiedId, getSpace, useMembers } from "@dxos/react-client/echo";
|
|
65
43
|
import { useIdentity } from "@dxos/react-client/halo";
|
|
66
|
-
import { Button, Tag, Tooltip, useThemeContext, useTranslation
|
|
44
|
+
import { Button, Tag, Tooltip, useThemeContext, useTranslation } from "@dxos/react-ui";
|
|
67
45
|
import { createBasicExtensions, createThemeExtensions, listener } from "@dxos/react-ui-editor";
|
|
68
46
|
import { getSize, hoverableControlItem, hoverableControls, hoverableFocusedWithinControls, mx } from "@dxos/react-ui-theme";
|
|
69
47
|
import { MessageTextbox, Thread, ThreadFooter, ThreadHeading } from "@dxos/react-ui-thread";
|
|
70
48
|
import { nonNullable } from "@dxos/util";
|
|
71
49
|
var sizeClass = getSize(4);
|
|
50
|
+
var commentControlClassNames = "!p-1 !min-bs-0 transition-opacity";
|
|
72
51
|
var ToggleResolvedButton = ({ isResolved, onResolve }) => {
|
|
73
|
-
const { t } =
|
|
52
|
+
const { t } = useTranslation(THREAD_PLUGIN);
|
|
74
53
|
const label = t(isResolved ? "mark as unresolved label" : "mark as resolved label");
|
|
75
|
-
return /* @__PURE__ */
|
|
54
|
+
return /* @__PURE__ */ React.createElement(Tooltip.Root, null, /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
|
|
76
55
|
asChild: true
|
|
77
|
-
}, /* @__PURE__ */
|
|
56
|
+
}, /* @__PURE__ */ React.createElement(Button, {
|
|
78
57
|
variant: "ghost",
|
|
79
58
|
"data-testid": "thread.toggle-resolved",
|
|
80
59
|
onClick: onResolve,
|
|
81
60
|
classNames: [
|
|
82
|
-
|
|
61
|
+
commentControlClassNames,
|
|
83
62
|
!isResolved && hoverableControlItem
|
|
84
63
|
]
|
|
85
|
-
}, /* @__PURE__ */
|
|
64
|
+
}, /* @__PURE__ */ React.createElement("span", {
|
|
86
65
|
className: "sr-only"
|
|
87
|
-
}, label), isResolved ? /* @__PURE__ */
|
|
66
|
+
}, label), isResolved ? /* @__PURE__ */ React.createElement(CheckCircle, {
|
|
88
67
|
className: sizeClass,
|
|
89
68
|
weight: "fill"
|
|
90
|
-
}) : /* @__PURE__ */
|
|
69
|
+
}) : /* @__PURE__ */ React.createElement(CheckCircle, {
|
|
91
70
|
className: sizeClass
|
|
92
|
-
}))), /* @__PURE__ */
|
|
71
|
+
}))), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, {
|
|
93
72
|
classNames: "z-[21]"
|
|
94
|
-
}, label, /* @__PURE__ */
|
|
73
|
+
}, label, /* @__PURE__ */ React.createElement(Tooltip.Arrow, null))));
|
|
95
74
|
};
|
|
96
75
|
var DeleteThreadButton = ({ onDelete }) => {
|
|
97
|
-
const { t } =
|
|
76
|
+
const { t } = useTranslation(THREAD_PLUGIN);
|
|
98
77
|
const label = t("delete thread label");
|
|
99
|
-
return /* @__PURE__ */
|
|
78
|
+
return /* @__PURE__ */ React.createElement(Tooltip.Root, null, /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
|
|
100
79
|
asChild: true
|
|
101
|
-
}, /* @__PURE__ */
|
|
80
|
+
}, /* @__PURE__ */ React.createElement(Button, {
|
|
102
81
|
variant: "ghost",
|
|
103
82
|
"data-testid": "thread.delete",
|
|
104
83
|
onClick: onDelete,
|
|
105
84
|
classNames: [
|
|
106
|
-
|
|
85
|
+
commentControlClassNames,
|
|
107
86
|
hoverableControlItem
|
|
108
87
|
]
|
|
109
|
-
}, /* @__PURE__ */
|
|
88
|
+
}, /* @__PURE__ */ React.createElement("span", {
|
|
110
89
|
className: "sr-only"
|
|
111
|
-
}, label), /* @__PURE__ */
|
|
90
|
+
}, label), /* @__PURE__ */ React.createElement(X, {
|
|
112
91
|
className: sizeClass
|
|
113
|
-
}))), /* @__PURE__ */
|
|
92
|
+
}))), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, {
|
|
114
93
|
classNames: "z-[21]"
|
|
115
|
-
}, label, /* @__PURE__ */
|
|
94
|
+
}, label, /* @__PURE__ */ React.createElement(Tooltip.Arrow, null))));
|
|
116
95
|
};
|
|
117
|
-
var CommentContainer = ({ thread, detached, context, current,
|
|
96
|
+
var CommentContainer = ({ thread, detached, context, current, onAttend, onThreadDelete, onMessageDelete, onResolve, onComment }) => {
|
|
118
97
|
const identity = useIdentity();
|
|
119
98
|
const space = getSpace(thread);
|
|
120
99
|
const members = useMembers(space?.key);
|
|
121
|
-
const activity = useStatus(space, thread
|
|
122
|
-
const { t } =
|
|
100
|
+
const activity = useStatus(space, fullyQualifiedId(thread));
|
|
101
|
+
const { t } = useTranslation(THREAD_PLUGIN);
|
|
123
102
|
const threadScrollRef = useRef(null);
|
|
124
|
-
const [autoFocus, setAutoFocus] = useState(!!autoFocusTextbox);
|
|
125
103
|
const { themeMode } = useThemeContext();
|
|
126
|
-
const textboxMetadata = getMessageMetadata(thread
|
|
104
|
+
const textboxMetadata = getMessageMetadata(fullyQualifiedId(thread), identity);
|
|
127
105
|
const [_count, _setCount] = useState(0);
|
|
128
106
|
const rerenderEditor = () => _setCount((count) => count + 1);
|
|
129
107
|
const messageRef = useRef("");
|
|
@@ -141,11 +119,6 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
|
|
|
141
119
|
], [
|
|
142
120
|
_count
|
|
143
121
|
]);
|
|
144
|
-
useEffect(() => {
|
|
145
|
-
setAutoFocus(!!autoFocusTextbox);
|
|
146
|
-
}, [
|
|
147
|
-
autoFocusTextbox
|
|
148
|
-
]);
|
|
149
122
|
const scrollToEnd = (behavior) => setTimeout(() => threadScrollRef.current?.scrollIntoView({
|
|
150
123
|
behavior,
|
|
151
124
|
block: "end"
|
|
@@ -164,7 +137,6 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
|
|
|
164
137
|
}));
|
|
165
138
|
onComment?.(thread);
|
|
166
139
|
messageRef.current = "";
|
|
167
|
-
setAutoFocus(true);
|
|
168
140
|
scrollToEnd("instant");
|
|
169
141
|
rerenderEditor();
|
|
170
142
|
return true;
|
|
@@ -172,44 +144,42 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
|
|
|
172
144
|
thread,
|
|
173
145
|
identity
|
|
174
146
|
]);
|
|
175
|
-
|
|
176
|
-
return /* @__PURE__ */ React2.createElement(Thread, {
|
|
147
|
+
return /* @__PURE__ */ React.createElement(Thread, {
|
|
177
148
|
onClickCapture: onAttend,
|
|
178
149
|
onFocusCapture: onAttend,
|
|
179
150
|
current,
|
|
180
|
-
id: thread
|
|
181
|
-
}, /* @__PURE__ */
|
|
151
|
+
id: fullyQualifiedId(thread)
|
|
152
|
+
}, /* @__PURE__ */ React.createElement("div", {
|
|
182
153
|
role: "none",
|
|
183
154
|
className: mx("col-span-2 grid grid-cols-[var(--rail-size)_1fr_min-content]", hoverableControls, hoverableFocusedWithinControls)
|
|
184
|
-
}, detached ? /* @__PURE__ */
|
|
155
|
+
}, detached ? /* @__PURE__ */ React.createElement(Tooltip.Root, null, /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
|
|
185
156
|
asChild: true
|
|
186
|
-
}, /* @__PURE__ */
|
|
157
|
+
}, /* @__PURE__ */ React.createElement(ThreadHeading, {
|
|
187
158
|
detached: true
|
|
188
|
-
}, thread.name
|
|
159
|
+
}, thread.name)), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, {
|
|
189
160
|
classNames: "z-[21]",
|
|
190
161
|
side: "top"
|
|
191
|
-
}, t("detached thread label"), /* @__PURE__ */
|
|
162
|
+
}, t("detached thread label"), /* @__PURE__ */ React.createElement(Tooltip.Arrow, null)))) : /* @__PURE__ */ React.createElement(ThreadHeading, null, thread.name), /* @__PURE__ */ React.createElement("div", {
|
|
192
163
|
className: "flex flex-row items-center pli-1"
|
|
193
|
-
}, thread.status === "staged" && /* @__PURE__ */
|
|
164
|
+
}, thread.status === "staged" && /* @__PURE__ */ React.createElement(Tag, {
|
|
194
165
|
palette: "neutral"
|
|
195
|
-
}, t("draft button")), onResolve && !(thread?.status === "staged") && /* @__PURE__ */
|
|
166
|
+
}, t("draft button")), onResolve && !(thread?.status === "staged") && /* @__PURE__ */ React.createElement(ToggleResolvedButton, {
|
|
196
167
|
isResolved: thread?.status === "resolved",
|
|
197
168
|
onResolve
|
|
198
|
-
}), onThreadDelete && /* @__PURE__ */
|
|
169
|
+
}), onThreadDelete && /* @__PURE__ */ React.createElement(DeleteThreadButton, {
|
|
199
170
|
onDelete: onThreadDelete
|
|
200
|
-
}))), thread.messages.filter(nonNullable).map((message) => /* @__PURE__ */
|
|
171
|
+
}))), thread.messages.filter(nonNullable).map((message) => /* @__PURE__ */ React.createElement(MessageContainer, {
|
|
201
172
|
key: message.id,
|
|
202
173
|
message,
|
|
203
174
|
members,
|
|
204
|
-
onDelete:
|
|
205
|
-
})), /* @__PURE__ */
|
|
175
|
+
onDelete: (id) => onMessageDelete?.(id)
|
|
176
|
+
})), /* @__PURE__ */ React.createElement(MessageTextbox, {
|
|
206
177
|
extensions,
|
|
207
|
-
autoFocus,
|
|
208
178
|
onSend: handleCreate,
|
|
209
179
|
...textboxMetadata
|
|
210
|
-
}), /* @__PURE__ */
|
|
180
|
+
}), /* @__PURE__ */ React.createElement(ThreadFooter, {
|
|
211
181
|
activity
|
|
212
|
-
}, t("activity message")), /* @__PURE__ */
|
|
182
|
+
}, t("activity message")), /* @__PURE__ */ React.createElement("div", {
|
|
213
183
|
role: "none",
|
|
214
184
|
className: "bs-px -mbs-px",
|
|
215
185
|
ref: threadScrollRef
|
|
@@ -217,26 +187,15 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
|
|
|
217
187
|
};
|
|
218
188
|
|
|
219
189
|
// packages/plugins/plugin-thread/src/components/CommentsContainer.tsx
|
|
220
|
-
import { ChatText
|
|
221
|
-
import
|
|
222
|
-
import {
|
|
223
|
-
import {
|
|
190
|
+
import { ChatText } from "@phosphor-icons/react";
|
|
191
|
+
import React2, { useEffect } from "react";
|
|
192
|
+
import { fullyQualifiedId as fullyQualifiedId2 } from "@dxos/react-client/echo";
|
|
193
|
+
import { useTranslation as useTranslation2, Trans } from "@dxos/react-ui";
|
|
224
194
|
import { descriptionText, mx as mx2 } from "@dxos/react-ui-theme";
|
|
225
|
-
var
|
|
226
|
-
const { t } =
|
|
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(() => {
|
|
195
|
+
var CommentsContainer = ({ threads: threads2, detached = [], currentId, showResolvedThreads, onThreadAttend, onThreadDelete, onMessageDelete, onThreadToggleResolved, ...props }) => {
|
|
196
|
+
const { t } = useTranslation2(THREAD_PLUGIN);
|
|
197
|
+
const filteredThreads = showResolvedThreads ? threads2 : threads2.filter((thread) => !(thread?.status === "resolved"));
|
|
198
|
+
useEffect(() => {
|
|
240
199
|
if (currentId) {
|
|
241
200
|
document.getElementById(currentId)?.scrollIntoView({
|
|
242
201
|
behavior: "smooth",
|
|
@@ -246,44 +205,260 @@ var CommentsContainer = ({ threads, detached = [], currentId, autoFocusCurrentTe
|
|
|
246
205
|
}, [
|
|
247
206
|
currentId
|
|
248
207
|
]);
|
|
249
|
-
return /* @__PURE__ */
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
onThreadDelete
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
onMessageDelete
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
208
|
+
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, filteredThreads.length > 0 ? filteredThreads.map((thread) => {
|
|
209
|
+
const threadId = fullyQualifiedId2(thread);
|
|
210
|
+
return /* @__PURE__ */ React2.createElement(CommentContainer, {
|
|
211
|
+
key: threadId,
|
|
212
|
+
thread,
|
|
213
|
+
current: currentId === threadId,
|
|
214
|
+
detached: detached.includes(threadId),
|
|
215
|
+
...onThreadAttend && {
|
|
216
|
+
onAttend: () => onThreadAttend(thread)
|
|
217
|
+
},
|
|
218
|
+
...onThreadDelete && {
|
|
219
|
+
onThreadDelete: () => onThreadDelete(thread)
|
|
220
|
+
},
|
|
221
|
+
...onMessageDelete && {
|
|
222
|
+
onMessageDelete: (messageId) => onMessageDelete(thread, messageId)
|
|
223
|
+
},
|
|
224
|
+
...onThreadToggleResolved && {
|
|
225
|
+
onResolve: () => onThreadToggleResolved(thread)
|
|
226
|
+
},
|
|
227
|
+
...props
|
|
228
|
+
});
|
|
229
|
+
}) : /* @__PURE__ */ React2.createElement("div", {
|
|
269
230
|
role: "alert",
|
|
270
231
|
className: mx2(descriptionText, "place-self-center border border-dashed border-neutral-400/50 rounded-lg text-center p-4 m-4")
|
|
271
|
-
}, /* @__PURE__ */
|
|
232
|
+
}, /* @__PURE__ */ React2.createElement("h2", {
|
|
272
233
|
className: "mbe-2 font-medium text-baseText"
|
|
273
|
-
}, t("no comments title")), /* @__PURE__ */
|
|
234
|
+
}, t("no comments title")), /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement(Trans, {
|
|
274
235
|
t,
|
|
275
236
|
i18nKey: "no comments message",
|
|
276
237
|
components: {
|
|
277
|
-
commentIcon: /* @__PURE__ */
|
|
238
|
+
commentIcon: /* @__PURE__ */ React2.createElement(ChatText, {
|
|
278
239
|
className: "inline-block"
|
|
279
240
|
})
|
|
280
241
|
}
|
|
281
242
|
}))));
|
|
282
243
|
};
|
|
283
244
|
|
|
245
|
+
// packages/plugins/plugin-thread/src/components/ThreadComplementary.tsx
|
|
246
|
+
import React3, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
|
|
247
|
+
import { LayoutAction, useIntentDispatcher, useResolvePlugins } from "@dxos/app-framework";
|
|
248
|
+
import { fullyQualifiedId as fullyQualifiedId3 } from "@dxos/react-client/echo";
|
|
249
|
+
import { ScrollArea } from "@dxos/react-ui";
|
|
250
|
+
import { useAttended } from "@dxos/react-ui-attention";
|
|
251
|
+
import { nonNullable as nonNullable2 } from "@dxos/util";
|
|
252
|
+
var providesThreadsConfig = (plugin) => "thread" in plugin.provides ? plugin : void 0;
|
|
253
|
+
var ThreadComplementary = ({ role, subject, drafts, current, showResolvedThreads }) => {
|
|
254
|
+
const dispatch = useIntentDispatcher();
|
|
255
|
+
const threadsIntegrators = useResolvePlugins(providesThreadsConfig);
|
|
256
|
+
const threadProvides = useMemo2(() => threadsIntegrators.map((p) => p.provides.thread), [
|
|
257
|
+
threadsIntegrators
|
|
258
|
+
]);
|
|
259
|
+
const createSort = useMemo2(() => threadProvides.find((p) => p.predicate(subject))?.createSort, [
|
|
260
|
+
threadProvides,
|
|
261
|
+
subject
|
|
262
|
+
]);
|
|
263
|
+
const sort = useMemo2(() => createSort?.(subject), [
|
|
264
|
+
createSort,
|
|
265
|
+
subject
|
|
266
|
+
]);
|
|
267
|
+
const threads2 = useMemo2(() => {
|
|
268
|
+
return subject.threads.concat(drafts ?? []).filter(nonNullable2);
|
|
269
|
+
}, [
|
|
270
|
+
JSON.stringify(subject.threads),
|
|
271
|
+
JSON.stringify(drafts)
|
|
272
|
+
]);
|
|
273
|
+
const detachedIds = useMemo2(() => {
|
|
274
|
+
return threads2.filter(({ anchor }) => !anchor).map((thread) => fullyQualifiedId3(thread));
|
|
275
|
+
}, [
|
|
276
|
+
threads2
|
|
277
|
+
]);
|
|
278
|
+
useEffect2(() => {
|
|
279
|
+
if (!sort) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
threads2.sort((a, b) => sort(a?.anchor, b?.anchor));
|
|
283
|
+
}, [
|
|
284
|
+
sort,
|
|
285
|
+
threads2
|
|
286
|
+
]);
|
|
287
|
+
const attended = useAttended();
|
|
288
|
+
const qualifiedSubjectId = fullyQualifiedId3(subject);
|
|
289
|
+
return /* @__PURE__ */ React3.createElement("div", {
|
|
290
|
+
role: "none",
|
|
291
|
+
className: "contents"
|
|
292
|
+
}, /* @__PURE__ */ React3.createElement(ScrollArea.Root, {
|
|
293
|
+
classNames: "row-span-2"
|
|
294
|
+
}, /* @__PURE__ */ React3.createElement(ScrollArea.Viewport, null, /* @__PURE__ */ React3.createElement(CommentsContainer, {
|
|
295
|
+
threads: threads2,
|
|
296
|
+
detached: detachedIds,
|
|
297
|
+
currentId: attended.includes(qualifiedSubjectId) ? current : void 0,
|
|
298
|
+
showResolvedThreads,
|
|
299
|
+
onThreadAttend: (thread) => {
|
|
300
|
+
const threadId = fullyQualifiedId3(thread);
|
|
301
|
+
if (current !== threadId) {
|
|
302
|
+
current = threadId;
|
|
303
|
+
void dispatch?.([
|
|
304
|
+
{
|
|
305
|
+
action: LayoutAction.SCROLL_INTO_VIEW,
|
|
306
|
+
data: {
|
|
307
|
+
id: fullyQualifiedId3(subject),
|
|
308
|
+
thread: threadId,
|
|
309
|
+
cursor: thread.anchor
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
]);
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
onThreadDelete: (thread) => {
|
|
316
|
+
return dispatch({
|
|
317
|
+
plugin: THREAD_PLUGIN,
|
|
318
|
+
action: ThreadAction.DELETE,
|
|
319
|
+
data: {
|
|
320
|
+
subject,
|
|
321
|
+
thread
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
},
|
|
325
|
+
onMessageDelete: (thread, messageId) => dispatch({
|
|
326
|
+
plugin: THREAD_PLUGIN,
|
|
327
|
+
action: ThreadAction.DELETE_MESSAGE,
|
|
328
|
+
data: {
|
|
329
|
+
subject,
|
|
330
|
+
thread,
|
|
331
|
+
messageId
|
|
332
|
+
}
|
|
333
|
+
}),
|
|
334
|
+
onThreadToggleResolved: (thread) => dispatch({
|
|
335
|
+
plugin: THREAD_PLUGIN,
|
|
336
|
+
action: ThreadAction.TOGGLE_RESOLVED,
|
|
337
|
+
data: {
|
|
338
|
+
thread
|
|
339
|
+
}
|
|
340
|
+
}),
|
|
341
|
+
onComment: (thread) => {
|
|
342
|
+
void dispatch({
|
|
343
|
+
action: ThreadAction.ON_MESSAGE_ADD,
|
|
344
|
+
data: {
|
|
345
|
+
thread,
|
|
346
|
+
subject
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
}), /* @__PURE__ */ React3.createElement("div", {
|
|
351
|
+
role: "none",
|
|
352
|
+
className: "bs-10"
|
|
353
|
+
}), /* @__PURE__ */ React3.createElement(ScrollArea.Scrollbar, null, /* @__PURE__ */ React3.createElement(ScrollArea.Thumb, null)))));
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
// packages/plugins/plugin-thread/src/components/ThreadSettings.tsx
|
|
357
|
+
import React4 from "react";
|
|
358
|
+
import { Input, useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
359
|
+
import { DeprecatedFormInput } from "@dxos/react-ui-data";
|
|
360
|
+
var ThreadSettings = ({ settings }) => {
|
|
361
|
+
const { t } = useTranslation3(THREAD_PLUGIN);
|
|
362
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(DeprecatedFormInput, {
|
|
363
|
+
label: t("settings standalone label")
|
|
364
|
+
}, /* @__PURE__ */ React4.createElement(Input.Switch, {
|
|
365
|
+
checked: settings.standalone,
|
|
366
|
+
onCheckedChange: (checked) => settings.standalone = !!checked
|
|
367
|
+
})));
|
|
368
|
+
};
|
|
369
|
+
|
|
284
370
|
// packages/plugins/plugin-thread/src/components/index.ts
|
|
285
|
-
var ThreadMain =
|
|
286
|
-
var ThreadArticle =
|
|
371
|
+
var ThreadMain = lazy(() => import("./ThreadMain-45OFO3G6.mjs"));
|
|
372
|
+
var ThreadArticle = lazy(() => import("./ThreadArticle-6RFOFTU2.mjs"));
|
|
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 = [
|
|
@@ -315,21 +490,22 @@ var translations_default = [
|
|
|
315
490
|
"mark as unresolved label": "Mark as unresolved",
|
|
316
491
|
"save message label": "Save",
|
|
317
492
|
"edit message label": "Edit",
|
|
318
|
-
"delete message label": "Delete message"
|
|
493
|
+
"delete message label": "Delete message",
|
|
494
|
+
"open comments panel label": "Show Comments"
|
|
319
495
|
}
|
|
320
496
|
}
|
|
321
497
|
}
|
|
322
498
|
];
|
|
323
499
|
|
|
324
500
|
// packages/plugins/plugin-thread/src/ThreadPlugin.tsx
|
|
501
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/plugin-thread/src/ThreadPlugin.tsx";
|
|
325
502
|
var initialViewState = {
|
|
326
503
|
showResolvedThreads: false
|
|
327
504
|
};
|
|
328
|
-
var providesThreadsConfig = (plugin) => "thread" in plugin.provides ? plugin : void 0;
|
|
329
505
|
var ThreadPlugin = () => {
|
|
330
506
|
const settings = new LocalStorageStore(THREAD_PLUGIN);
|
|
331
507
|
const state = create2({
|
|
332
|
-
|
|
508
|
+
drafts: {}
|
|
333
509
|
});
|
|
334
510
|
const viewStore = create2({});
|
|
335
511
|
const getViewState = (subjectId) => {
|
|
@@ -340,10 +516,8 @@ var ThreadPlugin = () => {
|
|
|
340
516
|
}
|
|
341
517
|
return viewStore[subjectId];
|
|
342
518
|
};
|
|
343
|
-
let attentionPlugin;
|
|
344
519
|
let navigationPlugin;
|
|
345
520
|
let intentPlugin;
|
|
346
|
-
let dispatch;
|
|
347
521
|
const unsubscribeCallbacks = [];
|
|
348
522
|
return {
|
|
349
523
|
meta: meta_default,
|
|
@@ -354,36 +528,8 @@ var ThreadPlugin = () => {
|
|
|
354
528
|
allowUndefined: true
|
|
355
529
|
})
|
|
356
530
|
});
|
|
357
|
-
attentionPlugin = resolvePlugin(plugins, parseAttentionPlugin);
|
|
358
531
|
navigationPlugin = resolvePlugin(plugins, parseNavigationPlugin);
|
|
359
532
|
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
533
|
},
|
|
388
534
|
unload: async () => {
|
|
389
535
|
unsubscribeCallbacks.forEach((unsubscribe) => unsubscribe());
|
|
@@ -394,17 +540,16 @@ var ThreadPlugin = () => {
|
|
|
394
540
|
records: {
|
|
395
541
|
[ChannelType.typename]: {
|
|
396
542
|
placeholder: [
|
|
397
|
-
"channel
|
|
543
|
+
"channel name placeholder",
|
|
398
544
|
{
|
|
399
545
|
ns: THREAD_PLUGIN
|
|
400
546
|
}
|
|
401
547
|
],
|
|
402
|
-
icon:
|
|
403
|
-
iconSymbol: "ph--chat--regular",
|
|
548
|
+
icon: "ph--chat--regular",
|
|
404
549
|
// TODO(wittjosiah): Move out of metadata.
|
|
405
550
|
loadReferences: (channel) => loadObjectReferences(channel, (channel2) => channel2.threads)
|
|
406
551
|
},
|
|
407
|
-
[
|
|
552
|
+
[ThreadType2.typename]: {
|
|
408
553
|
// TODO(wittjosiah): Move out of metadata.
|
|
409
554
|
loadReferences: (thread) => loadObjectReferences(thread, (thread2) => thread2.messages)
|
|
410
555
|
},
|
|
@@ -440,18 +585,34 @@ var ThreadPlugin = () => {
|
|
|
440
585
|
echo: {
|
|
441
586
|
schema: [
|
|
442
587
|
ChannelType,
|
|
443
|
-
|
|
588
|
+
ThreadType2,
|
|
444
589
|
MessageType2
|
|
445
590
|
]
|
|
446
591
|
},
|
|
592
|
+
complementary: {
|
|
593
|
+
panels: [
|
|
594
|
+
{
|
|
595
|
+
id: "comments",
|
|
596
|
+
label: [
|
|
597
|
+
"open comments panel label",
|
|
598
|
+
{
|
|
599
|
+
ns: THREAD_PLUGIN
|
|
600
|
+
}
|
|
601
|
+
],
|
|
602
|
+
icon: "ph--chat-text--regular"
|
|
603
|
+
}
|
|
604
|
+
]
|
|
605
|
+
},
|
|
447
606
|
graph: {
|
|
448
607
|
builder: (plugins) => {
|
|
449
608
|
const client = resolvePlugin(plugins, parseClientPlugin)?.provides.client;
|
|
450
|
-
const
|
|
609
|
+
const dispatch = resolvePlugin(plugins, parseIntentPlugin)?.provides.intent.dispatch;
|
|
451
610
|
const metadataResolver = resolvePlugin(plugins, parseMetadataResolverPlugin)?.provides.metadata.resolver;
|
|
452
|
-
if (!client || !
|
|
611
|
+
if (!client || !dispatch || !metadataResolver) {
|
|
453
612
|
return [];
|
|
454
613
|
}
|
|
614
|
+
const type = "orphan-comments-for-subject";
|
|
615
|
+
const icon = "ph--chat-text--regular";
|
|
455
616
|
return [
|
|
456
617
|
createExtension({
|
|
457
618
|
id: `${THREAD_PLUGIN}/comments-for-subject`,
|
|
@@ -459,29 +620,55 @@ var ThreadPlugin = () => {
|
|
|
459
620
|
if (!id.endsWith("~comments")) {
|
|
460
621
|
return;
|
|
461
622
|
}
|
|
462
|
-
const
|
|
463
|
-
const
|
|
623
|
+
const [subjectId] = id.split("~");
|
|
624
|
+
const { spaceId, objectId } = parseId(subjectId);
|
|
464
625
|
const space = client.spaces.get().find((space2) => space2.id === spaceId);
|
|
465
|
-
|
|
466
|
-
|
|
626
|
+
if (!objectId) {
|
|
627
|
+
return {
|
|
628
|
+
id,
|
|
629
|
+
type,
|
|
630
|
+
data: null,
|
|
631
|
+
properties: {
|
|
632
|
+
icon,
|
|
633
|
+
label: [
|
|
634
|
+
"unnamed object threads label",
|
|
635
|
+
{
|
|
636
|
+
ns: THREAD_PLUGIN
|
|
637
|
+
}
|
|
638
|
+
],
|
|
639
|
+
showResolvedThreads: false,
|
|
640
|
+
object: null,
|
|
641
|
+
space
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
const object = toSignal((onChange) => {
|
|
646
|
+
const timeout = setTimeout(async () => {
|
|
647
|
+
await space?.db.loadObjectById(objectId);
|
|
648
|
+
onChange();
|
|
649
|
+
});
|
|
650
|
+
return () => clearTimeout(timeout);
|
|
651
|
+
}, () => space?.db.getObjectById(objectId), subjectId);
|
|
652
|
+
if (!object || !subjectId) {
|
|
467
653
|
return;
|
|
468
654
|
}
|
|
469
|
-
const
|
|
470
|
-
const label =
|
|
655
|
+
const meta = metadataResolver(getTypename(object) ?? "");
|
|
656
|
+
const label = meta.label?.(object) || object.name || meta.placeholder || [
|
|
471
657
|
"unnamed object threads label",
|
|
472
658
|
{
|
|
473
659
|
ns: THREAD_PLUGIN
|
|
474
660
|
}
|
|
475
661
|
];
|
|
476
|
-
const viewState = getViewState(
|
|
662
|
+
const viewState = getViewState(subjectId);
|
|
477
663
|
return {
|
|
478
664
|
id,
|
|
479
|
-
type
|
|
480
|
-
data:
|
|
665
|
+
type,
|
|
666
|
+
data: null,
|
|
481
667
|
properties: {
|
|
482
|
-
icon
|
|
668
|
+
icon,
|
|
483
669
|
label,
|
|
484
|
-
showResolvedThreads: viewState.showResolvedThreads
|
|
670
|
+
showResolvedThreads: viewState.showResolvedThreads,
|
|
671
|
+
object
|
|
485
672
|
}
|
|
486
673
|
};
|
|
487
674
|
},
|
|
@@ -495,7 +682,7 @@ var ThreadPlugin = () => {
|
|
|
495
682
|
const toggle = () => {
|
|
496
683
|
const newToggleState = !viewState.showResolvedThreads;
|
|
497
684
|
viewState.showResolvedThreads = newToggleState;
|
|
498
|
-
void
|
|
685
|
+
void dispatch({
|
|
499
686
|
action: ObservabilityAction.SEND_EVENT,
|
|
500
687
|
data: {
|
|
501
688
|
name: "threads.toggle-show-resolved",
|
|
@@ -520,7 +707,8 @@ var ThreadPlugin = () => {
|
|
|
520
707
|
],
|
|
521
708
|
menuItemType: "toggle",
|
|
522
709
|
isChecked: viewState.showResolvedThreads,
|
|
523
|
-
testId: "threadPlugin.toggleShowResolved"
|
|
710
|
+
testId: "threadPlugin.toggleShowResolved",
|
|
711
|
+
icon: viewState.showResolvedThreads ? "ph--eye-slash--regular" : "ph--eye--regular"
|
|
524
712
|
}
|
|
525
713
|
}
|
|
526
714
|
];
|
|
@@ -542,7 +730,7 @@ var ThreadPlugin = () => {
|
|
|
542
730
|
{
|
|
543
731
|
id: `${THREAD_PLUGIN}/create/${node.id}`,
|
|
544
732
|
data: async () => {
|
|
545
|
-
await
|
|
733
|
+
await dispatch([
|
|
546
734
|
{
|
|
547
735
|
plugin: THREAD_PLUGIN,
|
|
548
736
|
action: ThreadAction.CREATE
|
|
@@ -565,8 +753,7 @@ var ThreadPlugin = () => {
|
|
|
565
753
|
ns: THREAD_PLUGIN
|
|
566
754
|
}
|
|
567
755
|
],
|
|
568
|
-
icon:
|
|
569
|
-
iconSymbol: "ph--chat--regular",
|
|
756
|
+
icon: "ph--chat--regular",
|
|
570
757
|
testId: "threadPlugin.createObject"
|
|
571
758
|
}
|
|
572
759
|
}
|
|
@@ -589,11 +776,8 @@ var ThreadPlugin = () => {
|
|
|
589
776
|
settings: settings.values
|
|
590
777
|
}) : null;
|
|
591
778
|
}
|
|
592
|
-
case "article":
|
|
593
|
-
case "complementary": {
|
|
779
|
+
case "article": {
|
|
594
780
|
const location = navigationPlugin?.provides.location;
|
|
595
|
-
const threadsIntegrators = useResolvePlugins(providesThreadsConfig);
|
|
596
|
-
const threadProvides = threadsIntegrators.map((p) => p.provides.thread);
|
|
597
781
|
if (data.object instanceof ChannelType && data.object.threads[0]) {
|
|
598
782
|
const channel = data.object;
|
|
599
783
|
if (isLayoutParts(location?.active) && location.active.main) {
|
|
@@ -601,7 +785,7 @@ var ThreadPlugin = () => {
|
|
|
601
785
|
const currentPosition = layoutEntries.findIndex((entry) => channel.id === entry.id);
|
|
602
786
|
if (currentPosition > 0) {
|
|
603
787
|
const objectToTheLeft = layoutEntries[currentPosition - 1];
|
|
604
|
-
const context =
|
|
788
|
+
const context = getSpace3(data.object)?.db.getObjectById(objectToTheLeft.id);
|
|
605
789
|
return /* @__PURE__ */ React5.createElement(ThreadArticle, {
|
|
606
790
|
thread: data.object.threads[0],
|
|
607
791
|
context
|
|
@@ -612,92 +796,27 @@ var ThreadPlugin = () => {
|
|
|
612
796
|
thread: data.object.threads[0]
|
|
613
797
|
});
|
|
614
798
|
}
|
|
615
|
-
if (data.subject instanceof
|
|
799
|
+
if (data.subject instanceof ThreadType2) {
|
|
616
800
|
return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(ChatHeading, {
|
|
617
801
|
attendableId: data.subject.id
|
|
618
802
|
}), /* @__PURE__ */ React5.createElement(ChatContainer, {
|
|
619
803
|
thread: data.subject
|
|
620
804
|
}));
|
|
621
805
|
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
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)))));
|
|
806
|
+
break;
|
|
807
|
+
}
|
|
808
|
+
case "complementary--comments": {
|
|
809
|
+
if (data.subject && typeof data.subject === "object" && "threads" in data.subject && Array.isArray(data.subject.threads) && !(data.subject instanceof ChannelType)) {
|
|
810
|
+
const { showResolvedThreads } = getViewState(fullyQualifiedId5(data.subject));
|
|
811
|
+
return /* @__PURE__ */ React5.createElement(ThreadComplementary, {
|
|
812
|
+
role,
|
|
813
|
+
subject: data.subject,
|
|
814
|
+
drafts: state.drafts[fullyQualifiedId5(data.subject)],
|
|
815
|
+
current: state.current,
|
|
816
|
+
showResolvedThreads
|
|
817
|
+
});
|
|
700
818
|
}
|
|
819
|
+
break;
|
|
701
820
|
}
|
|
702
821
|
}
|
|
703
822
|
return null;
|
|
@@ -709,18 +828,31 @@ var ThreadPlugin = () => {
|
|
|
709
828
|
case ThreadAction.CREATE: {
|
|
710
829
|
if (intent.data && intent.data.cursor !== void 0) {
|
|
711
830
|
const { cursor, name, subject } = intent.data;
|
|
712
|
-
|
|
713
|
-
|
|
831
|
+
if (subject?.threads === void 0) {
|
|
832
|
+
try {
|
|
833
|
+
subject.threads = [];
|
|
834
|
+
} catch (err) {
|
|
835
|
+
log.error("Subject does not support threads array", subject?.typename, {
|
|
836
|
+
F: __dxlog_file,
|
|
837
|
+
L: 357,
|
|
838
|
+
S: void 0,
|
|
839
|
+
C: (f, a) => f(...a)
|
|
840
|
+
});
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
const subjectId = fullyQualifiedId5(subject);
|
|
845
|
+
const thread = create2(ThreadType2, {
|
|
714
846
|
name,
|
|
715
847
|
anchor: cursor,
|
|
716
848
|
messages: [],
|
|
717
849
|
status: "staged"
|
|
718
850
|
});
|
|
719
|
-
const
|
|
720
|
-
if (
|
|
721
|
-
|
|
851
|
+
const draft = state.drafts[subjectId];
|
|
852
|
+
if (draft) {
|
|
853
|
+
draft.push(thread);
|
|
722
854
|
} else {
|
|
723
|
-
state.
|
|
855
|
+
state.drafts[subjectId] = [
|
|
724
856
|
thread
|
|
725
857
|
];
|
|
726
858
|
}
|
|
@@ -729,25 +861,27 @@ var ThreadPlugin = () => {
|
|
|
729
861
|
intents: [
|
|
730
862
|
[
|
|
731
863
|
{
|
|
732
|
-
action:
|
|
864
|
+
action: ThreadAction.SELECT,
|
|
733
865
|
data: {
|
|
734
|
-
|
|
735
|
-
complementary: `${subjectId}${SLUG_PATH_SEPARATOR}comments${SLUG_COLLECTION_INDICATOR}`
|
|
736
|
-
}
|
|
866
|
+
current: fullyQualifiedId5(thread)
|
|
737
867
|
}
|
|
738
|
-
}
|
|
868
|
+
}
|
|
869
|
+
],
|
|
870
|
+
[
|
|
739
871
|
{
|
|
740
|
-
action:
|
|
872
|
+
action: NavigationAction.OPEN,
|
|
741
873
|
data: {
|
|
742
|
-
|
|
743
|
-
|
|
874
|
+
activeParts: {
|
|
875
|
+
complementary: "comments"
|
|
876
|
+
}
|
|
744
877
|
}
|
|
745
|
-
}
|
|
878
|
+
}
|
|
879
|
+
],
|
|
880
|
+
[
|
|
746
881
|
{
|
|
747
|
-
action:
|
|
882
|
+
action: LayoutAction2.SET_LAYOUT,
|
|
748
883
|
data: {
|
|
749
884
|
element: "complementary",
|
|
750
|
-
subject: subjectId,
|
|
751
885
|
state: true
|
|
752
886
|
}
|
|
753
887
|
}
|
|
@@ -758,7 +892,7 @@ var ThreadPlugin = () => {
|
|
|
758
892
|
return {
|
|
759
893
|
data: create2(ChannelType, {
|
|
760
894
|
threads: [
|
|
761
|
-
create2(
|
|
895
|
+
create2(ThreadType2, {
|
|
762
896
|
messages: []
|
|
763
897
|
})
|
|
764
898
|
]
|
|
@@ -767,15 +901,26 @@ var ThreadPlugin = () => {
|
|
|
767
901
|
}
|
|
768
902
|
}
|
|
769
903
|
case ThreadAction.SELECT: {
|
|
770
|
-
state.focus = intent.data?.current === state.current ? state.focus : intent.data?.focus;
|
|
771
904
|
state.current = intent.data?.current;
|
|
772
905
|
return {
|
|
773
|
-
data: true
|
|
906
|
+
data: true,
|
|
907
|
+
intents: !intent.data?.skipOpen ? [
|
|
908
|
+
[
|
|
909
|
+
{
|
|
910
|
+
action: NavigationAction.OPEN,
|
|
911
|
+
data: {
|
|
912
|
+
activeParts: {
|
|
913
|
+
complementary: "comments"
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
]
|
|
918
|
+
] : []
|
|
774
919
|
};
|
|
775
920
|
}
|
|
776
921
|
case ThreadAction.TOGGLE_RESOLVED: {
|
|
777
922
|
const { thread } = intent.data ?? {};
|
|
778
|
-
if (!(thread instanceof
|
|
923
|
+
if (!(thread instanceof ThreadType2)) {
|
|
779
924
|
return;
|
|
780
925
|
}
|
|
781
926
|
if (thread.status === "active" || thread.status === void 0) {
|
|
@@ -783,9 +928,10 @@ var ThreadPlugin = () => {
|
|
|
783
928
|
} else if (thread.status === "resolved") {
|
|
784
929
|
thread.status = "active";
|
|
785
930
|
}
|
|
786
|
-
const space =
|
|
931
|
+
const space = getSpace3(thread);
|
|
787
932
|
const spaceId = space?.id;
|
|
788
933
|
return {
|
|
934
|
+
data: true,
|
|
789
935
|
intents: [
|
|
790
936
|
[
|
|
791
937
|
{
|
|
@@ -804,19 +950,21 @@ var ThreadPlugin = () => {
|
|
|
804
950
|
}
|
|
805
951
|
case ThreadAction.DELETE: {
|
|
806
952
|
const { subject, thread } = intent.data ?? {};
|
|
807
|
-
if (!(
|
|
953
|
+
if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject)) {
|
|
808
954
|
return;
|
|
809
955
|
}
|
|
810
|
-
const subjectId =
|
|
811
|
-
const
|
|
812
|
-
if (
|
|
813
|
-
const index =
|
|
956
|
+
const subjectId = fullyQualifiedId5(subject);
|
|
957
|
+
const draft = state.drafts[subjectId];
|
|
958
|
+
if (draft) {
|
|
959
|
+
const index = draft.findIndex((t) => t.id === thread.id);
|
|
814
960
|
if (index !== -1) {
|
|
815
|
-
|
|
816
|
-
return
|
|
961
|
+
draft.splice(index, 1);
|
|
962
|
+
return {
|
|
963
|
+
data: true
|
|
964
|
+
};
|
|
817
965
|
}
|
|
818
966
|
}
|
|
819
|
-
const space =
|
|
967
|
+
const space = getSpace3(thread);
|
|
820
968
|
if (!space || !subject.threads) {
|
|
821
969
|
return;
|
|
822
970
|
}
|
|
@@ -874,22 +1022,22 @@ var ThreadPlugin = () => {
|
|
|
874
1022
|
}
|
|
875
1023
|
case ThreadAction.ON_MESSAGE_ADD: {
|
|
876
1024
|
const { thread, subject } = intent.data ?? {};
|
|
877
|
-
if (!(thread instanceof
|
|
1025
|
+
if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject && Array.isArray(subject.threads))) {
|
|
878
1026
|
return;
|
|
879
1027
|
}
|
|
880
|
-
const subjectId =
|
|
881
|
-
const space =
|
|
1028
|
+
const subjectId = fullyQualifiedId5(subject);
|
|
1029
|
+
const space = getSpace3(subject);
|
|
882
1030
|
const intents = [];
|
|
883
1031
|
const analyticsProperties = {
|
|
884
1032
|
threadId: thread.id,
|
|
885
1033
|
spaceId: space?.id
|
|
886
1034
|
};
|
|
887
|
-
if (state.
|
|
1035
|
+
if (state.drafts[subjectId]?.find((t) => t === thread)) {
|
|
888
1036
|
thread.status = "active";
|
|
889
1037
|
subject.threads ? subject.threads.push(thread) : subject.threads = [
|
|
890
1038
|
thread
|
|
891
1039
|
];
|
|
892
|
-
state.
|
|
1040
|
+
state.drafts[subjectId] = state.drafts[subjectId]?.filter(({ id }) => id !== thread.id);
|
|
893
1041
|
intents.push({
|
|
894
1042
|
action: ObservabilityAction.SEND_EVENT,
|
|
895
1043
|
data: {
|
|
@@ -917,8 +1065,8 @@ var ThreadPlugin = () => {
|
|
|
917
1065
|
}
|
|
918
1066
|
case ThreadAction.DELETE_MESSAGE: {
|
|
919
1067
|
const { subject, thread, messageId } = intent.data ?? {};
|
|
920
|
-
const space =
|
|
921
|
-
if (!(
|
|
1068
|
+
const space = getSpace3(subject);
|
|
1069
|
+
if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject)) {
|
|
922
1070
|
return;
|
|
923
1071
|
}
|
|
924
1072
|
if (!intent.undo) {
|
|
@@ -960,7 +1108,7 @@ var ThreadPlugin = () => {
|
|
|
960
1108
|
name: "threads.message.delete",
|
|
961
1109
|
properties: {
|
|
962
1110
|
threadId: thread.id,
|
|
963
|
-
spaceId: space
|
|
1111
|
+
spaceId: space?.id
|
|
964
1112
|
}
|
|
965
1113
|
}
|
|
966
1114
|
}
|
|
@@ -984,7 +1132,7 @@ var ThreadPlugin = () => {
|
|
|
984
1132
|
name: "threads.message.undo-delete",
|
|
985
1133
|
properties: {
|
|
986
1134
|
threadId: thread.id,
|
|
987
|
-
spaceId: space
|
|
1135
|
+
spaceId: space?.id
|
|
988
1136
|
}
|
|
989
1137
|
}
|
|
990
1138
|
}
|
|
@@ -997,92 +1145,8 @@ var ThreadPlugin = () => {
|
|
|
997
1145
|
}
|
|
998
1146
|
},
|
|
999
1147
|
markdown: {
|
|
1000
|
-
// TODO(burdon): Factor out extension factory into separate file (for simplicity).
|
|
1001
1148
|
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
|
-
];
|
|
1149
|
+
return threads(state, doc, intentPlugin?.provides.intent.dispatch);
|
|
1086
1150
|
}
|
|
1087
1151
|
}
|
|
1088
1152
|
}
|