@seafile/sdoc-editor 2.0.69 → 2.0.71

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 (58) hide show
  1. package/dist/basic-sdk/comment/comment-decorate.js +17 -17
  2. package/dist/basic-sdk/comment/components/comment-context-menu/index.css +16 -0
  3. package/dist/basic-sdk/comment/components/comment-context-menu/index.js +38 -0
  4. package/dist/basic-sdk/comment/components/comment-context-menu/menu-item.js +57 -0
  5. package/dist/basic-sdk/comment/components/comment-editor.js +5 -2
  6. package/dist/basic-sdk/comment/components/comment-item-collapse-wrapper.js +17 -1
  7. package/dist/basic-sdk/comment/components/comment-item-wrapper.js +85 -30
  8. package/dist/basic-sdk/comment/components/comment-list.css +34 -0
  9. package/dist/basic-sdk/comment/components/comment-list.js +96 -20
  10. package/dist/basic-sdk/comment/components/editor-comment.js +117 -57
  11. package/dist/basic-sdk/comment/components/elements-comment-count/index.js +15 -3
  12. package/dist/basic-sdk/comment/components/global-comment/index.css +25 -0
  13. package/dist/basic-sdk/comment/helper.js +111 -2
  14. package/dist/basic-sdk/comment/reducer/comment-reducer.js +2 -3
  15. package/dist/basic-sdk/constants/index.js +2 -1
  16. package/dist/basic-sdk/editor/sdoc-editor.js +4 -4
  17. package/dist/basic-sdk/extension/commons/color-menu/index.js +3 -3
  18. package/dist/basic-sdk/extension/commons/file-insert-dialog/index.js +5 -4
  19. package/dist/basic-sdk/extension/commons/wiki-file-insert-dialog/index.js +5 -4
  20. package/dist/basic-sdk/extension/core/queries/index.js +2 -3
  21. package/dist/basic-sdk/extension/core/utils/index.js +1 -29
  22. package/dist/basic-sdk/extension/plugins/ai/ai-icon/index.js +2 -2
  23. package/dist/basic-sdk/extension/plugins/ai/ai-module/helpers.js +4 -0
  24. package/dist/basic-sdk/extension/plugins/font/menu/font-family/index.js +1 -1
  25. package/dist/basic-sdk/extension/plugins/header/placeholder.js +33 -0
  26. package/dist/basic-sdk/extension/plugins/header/render-elem.js +2 -2
  27. package/dist/basic-sdk/extension/plugins/multi-column/helper.js +1 -1
  28. package/dist/basic-sdk/extension/plugins/paragraph/render-elem.js +2 -1
  29. package/dist/basic-sdk/extension/plugins/table/menu/color-selector-popover/index.js +3 -3
  30. package/dist/basic-sdk/extension/plugins/text-style/menu/index.js +2 -1
  31. package/dist/basic-sdk/extension/plugins/text-style/render-elem.js +28 -4
  32. package/dist/basic-sdk/hooks/use-selection-position.js +51 -30
  33. package/dist/basic-sdk/layout/article-container.js +1 -1
  34. package/dist/basic-sdk/layout/editor-content.js +1 -1
  35. package/dist/basic-sdk/node-id/helpers.js +26 -2
  36. package/dist/basic-sdk/node-id/index.js +37 -2
  37. package/dist/basic-sdk/right-panel/index.js +4 -4
  38. package/dist/basic-sdk/utils/common-utils.js +43 -0
  39. package/dist/basic-sdk/utils/default-mode.js +1 -1
  40. package/dist/basic-sdk/utils/document-utils.js +16 -2
  41. package/dist/basic-sdk/utils/full-width-mode.js +1 -1
  42. package/dist/basic-sdk/views/published-revision-diff-viewer.js +1 -1
  43. package/dist/basic-sdk/views/revision-diff-viewer.js +1 -1
  44. package/dist/basic-sdk/views/sdoc-diff-viewer.js +1 -1
  45. package/dist/basic-sdk/views/sdoc-viewer.js +2 -2
  46. package/dist/basic-sdk/views/sdoc-wiki-viewer.js +2 -2
  47. package/dist/components/doc-operations/more-operations.js +1 -1
  48. package/dist/layout/layout.js +3 -3
  49. package/dist/pages/simple-viewer.js +1 -1
  50. package/dist/plugin-module/layout/editor-content.js +1 -1
  51. package/dist/plugin-module/views/plugin-viewer.js +2 -2
  52. package/dist/utils/index.js +2 -61
  53. package/package.json +1 -1
  54. package/public/locales/en/sdoc-editor.json +2 -1
  55. package/public/locales/zh_CN/sdoc-editor.json +2 -1
  56. package/dist/plugin-module/assets/css/sdoc-wiki-viewer.css +0 -28
  57. /package/dist/{assets → basic-sdk/assets}/css/diff-viewer.css +0 -0
  58. /package/dist/{utils → basic-sdk/utils}/local-storage-utils.js +0 -0
@@ -8,10 +8,12 @@ Object.defineProperty(exports, "__esModule", {
8
8
  exports.default = void 0;
9
9
  var _react = _interopRequireWildcard(require("react"));
10
10
  var _slate = require("@seafile/slate");
11
+ var _classnames = _interopRequireDefault(require("classnames"));
11
12
  var _constants = require("../../constants");
12
- var _constants2 = require("../../extension/constants");
13
+ var _helpers = require("../../extension/plugins/ai/ai-module/helpers");
13
14
  var _useSelectionElement = require("../../hooks/use-selection-element");
14
15
  var _useSelectionUpdate = _interopRequireDefault(require("../../hooks/use-selection-update"));
16
+ var _eventBus = _interopRequireDefault(require("../../utils/event-bus"));
15
17
  var _helper = require("../helper");
16
18
  var _useCommentContext = require("../hooks/comment-hooks/use-comment-context");
17
19
  var _index = require("../utils/index");
@@ -28,39 +30,84 @@ const EditorComment = _ref => {
28
30
  const currentSelectionElement = (0, _useSelectionElement.useSelectionElement)({
29
31
  editor
30
32
  }); // The slate node of the current cursor line
31
- const [activeElement, setActiveElement] = (0, _react.useState)(null); // The slate node currently activated by clicking
33
+ const [activeElementIds, setActiveElementIds] = (0, _react.useState)([]); // The elements currently activated by clicking
32
34
  const [isShowComments, setIsShowComments] = (0, _react.useState)(false);
33
35
  const [commentDetail, setCommentDetail] = (0, _react.useState)({});
34
- const onAddCommentToggle = (0, _react.useCallback)(event => {
35
- event.stopPropagation();
36
- let activeElement = currentSelectionElement;
37
- // Add comments to image elements in the image block
38
- if (currentSelectionElement.type === _constants2.ELEMENT_TYPE.IMAGE_BLOCK) {
39
- activeElement = currentSelectionElement.children.find(item => (item === null || item === void 0 ? void 0 : item.type) === _constants2.ELEMENT_TYPE.IMAGE);
40
- }
41
- setActiveElement(activeElement);
42
- setIsShowComments(true);
36
+ const [isContextComment, setIsContextComment] = (0, _react.useState)(false);
37
+ const [isClickedContextComment, setIsClickedContextComment] = (0, _react.useState)(false);
38
+ const commentedDomRef = (0, _react.useRef)(null);
39
+ const hiddenComment = (0, _react.useCallback)(() => {
43
40
  setCommentDetail({});
44
- }, [currentSelectionElement]);
45
- const onSelectElement = (0, _react.useCallback)(elementId => {
46
- const activeElement = (0, _index.getCommentElementById)(elementId, editor);
47
- setActiveElement(activeElement);
48
- const unresolvedComments = element_comments_map[elementId].filter(item => !item.resolved);
49
- setCommentDetail(unresolvedComments[0]);
41
+ setIsShowComments(false);
42
+ setIsContextComment(false);
43
+ (0, _helpers.removeMarks)(editor);
44
+ setIsClickedContextComment(false);
45
+ }, [editor]);
46
+ const onSelectElement = (0, _react.useCallback)(function (elementId) {
47
+ let isClickInContext = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
48
+ if (!isClickInContext) {
49
+ hiddenComment();
50
+ const activeElementIds = [elementId];
51
+ setActiveElementIds(activeElementIds);
52
+ const unresolvedComments = element_comments_map[elementId].filter(item => !item.resolved);
53
+ setCommentDetail({
54
+ ...unresolvedComments
55
+ });
56
+ setIsClickedContextComment(false);
57
+ }
50
58
  setIsShowComments(true);
51
- }, [editor, element_comments_map]);
59
+ if (isClickInContext) {
60
+ const clickedComments = [];
61
+ for (const comments of Object.values(editor.element_comments_map)) {
62
+ for (const comment of comments) {
63
+ if (elementId.includes(comment.detail.text_comment_id)) {
64
+ clickedComments.push(comment);
65
+ }
66
+ }
67
+ }
68
+ setCommentDetail({
69
+ ...clickedComments
70
+ });
71
+ setIsClickedContextComment(true);
72
+ }
73
+ }, [editor, element_comments_map, hiddenComment]);
74
+ (0, _react.useEffect)(() => {
75
+ const handleHoverContextComment = event => {
76
+ var _parentDom$className;
77
+ const parentDom = event.target.parentElement;
78
+ if (parentDom !== null && parentDom !== void 0 && (_parentDom$className = parentDom.className) !== null && _parentDom$className !== void 0 && _parentDom$className.includes('sdoc_comment_')) {
79
+ const isHover = event.type === 'mouseover';
80
+ const matchedAttributes = parentDom.className.split(' ').filter(cls => cls.startsWith('sdoc_comment_'));
81
+ matchedAttributes.forEach(className => {
82
+ const el = document.querySelectorAll(`.${className}`);
83
+ el.forEach(el => {
84
+ el.style.textDecoration = isHover ? 'underline #eb8205' : '';
85
+ el.style.textDecorationThickness = isHover ? '2px' : '';
86
+ });
87
+ });
88
+ }
89
+ };
90
+ document.addEventListener('mouseover', handleHoverContextComment);
91
+ document.addEventListener('mouseout', handleHoverContextComment);
92
+ return () => {
93
+ document.removeEventListener('mouseover', handleHoverContextComment);
94
+ document.removeEventListener('mouseout', handleHoverContextComment);
95
+ };
96
+ }, []);
52
97
  const onSetCommentDetail = (0, _react.useCallback)(comment => {
53
98
  setCommentDetail(comment);
54
99
  }, []);
55
- const hiddenComment = (0, _react.useCallback)(() => {
56
- setCommentDetail({});
57
- setIsShowComments(false);
58
- }, []);
59
100
 
60
101
  // Comments are updated to modify the current comment
61
102
  (0, _react.useEffect)(() => {
62
- if (activeElement) {
63
- const unresolvedComments = element_comments_map[activeElement.id].filter(item => !item.resolved);
103
+ if (isContextComment && activeElementIds) {
104
+ const unresolvedComments = element_comments_map[activeElementIds[0].element.id].filter(item => !item.resolved);
105
+ if (unresolvedComments.length === 0) {
106
+ setIsShowComments(false);
107
+ }
108
+ }
109
+ if (activeElementIds && !Array.isArray(activeElementIds)) {
110
+ const unresolvedComments = element_comments_map[activeElementIds.id].filter(item => !item.resolved);
64
111
  if (unresolvedComments.length === 0) {
65
112
  setIsShowComments(false);
66
113
  }
@@ -72,53 +119,66 @@ const EditorComment = _ref => {
72
119
  if (isShowComments) {
73
120
  hiddenComment();
74
121
  }
75
- // eslint-disable-next-line react-hooks/exhaustive-deps
76
- }, [currentSelectionElement]);
77
- const cursor = (0, _helper.useCursorPosition)();
78
- const style = (0, _react.useMemo)(() => {
79
- var _Node$string;
80
- if (currentSelectionElement && ((_Node$string = _slate.Node.string(currentSelectionElement)) === null || _Node$string === void 0 ? void 0 : _Node$string.length) === 0 && !currentSelectionElement.children.find(n => n.type === _constants2.ELEMENT_TYPE.IMAGE)) {
81
- return {
82
- top: '-99999px'
83
- };
122
+ if (isContextComment) {
123
+ (0, _helpers.removeMarks)(editor);
84
124
  }
85
- const comments = element_comments_map[currentSelectionElement === null || currentSelectionElement === void 0 ? void 0 : currentSelectionElement.id];
86
- const unresolvedComments = comments && comments.filter(item => !item.resolved);
87
- const hasComments = unresolvedComments && unresolvedComments.length > 0;
88
- if (hasComments) return {
89
- top: '-99999px'
125
+ // eslint-disable-next-line react-hooks/exhaustive-deps
126
+ }, [currentSelectionElement, editor.selection]);
127
+ (0, _react.useEffect)(() => {
128
+ const handleAddContextComment = () => {
129
+ // Add temporary marks for selection
130
+ _slate.Editor.addMark(editor, 'comment', true);
131
+ setTimeout(() => {
132
+ const activeElementIds = (0, _helper.getSelectedElemIds)(editor);
133
+ const lastSelectedDom = (0, _helper.getDomById)(activeElementIds[activeElementIds.length - 1]);
134
+ commentedDomRef.current = lastSelectedDom;
135
+ setActiveElementIds(activeElementIds);
136
+ setIsShowComments(true);
137
+ setCommentDetail({});
138
+ setIsContextComment(true);
139
+ }, 0);
90
140
  };
91
- if (cursor.y === 0 || isShowComments) return {
92
- top: '-99999px'
141
+ const handleClickCommentedText = event => {
142
+ const parentDom = event.target.parentElement;
143
+ if (parentDom.className.split(/\s+/).some(cls => cls.startsWith('sdoc_comment'))) {
144
+ commentedDomRef.current = parentDom;
145
+ const matchedAttributes = parentDom.className.split(' ').filter(cls => cls.startsWith('sdoc_comment_'));
146
+ const clickedCommmentIdArray = matchedAttributes.map(item => item.replace('sdoc_comment_', ''));
147
+ onSelectElement(clickedCommmentIdArray, true);
148
+ }
93
149
  };
94
- return {
95
- top: cursor.y,
96
- zIndex: _constants.Z_INDEX.COMMENT_ADD
150
+ const eventBus = _eventBus.default.getInstance();
151
+ const unsubscribeAddContextComment = eventBus.subscribe(_constants.INTERNAL_EVENT.ADD_CONTEXT_COMMENT, handleAddContextComment);
152
+ document.addEventListener('click', handleClickCommentedText);
153
+ return () => {
154
+ unsubscribeAddContextComment();
155
+ document.removeEventListener('click', handleClickCommentedText);
97
156
  };
98
- }, [currentSelectionElement, element_comments_map, cursor.y, isShowComments]);
157
+ }, [editor, onSelectElement]);
99
158
  return /*#__PURE__*/_react.default.createElement("div", {
100
159
  className: "sdoc-comment-container"
101
160
  }, /*#__PURE__*/_react.default.createElement("div", {
102
161
  className: "comment-container-main"
103
162
  }), /*#__PURE__*/_react.default.createElement("div", {
104
- className: "comment-container-right"
105
- }, /*#__PURE__*/_react.default.createElement("div", {
106
- className: "comment-add-wrapper",
107
- style: style
108
- }, /*#__PURE__*/_react.default.createElement("span", {
109
- className: "add-comment-icon",
110
- onClick: onAddCommentToggle
111
- }, /*#__PURE__*/_react.default.createElement("i", {
112
- className: "sdocfont sdoc-add-comment mr-1"
113
- }))), /*#__PURE__*/_react.default.createElement(_elementsCommentCount.default, {
163
+ className: (0, _classnames.default)('comment-container-right', {
164
+ 'isContextComment': isContextComment
165
+ })
166
+ }, /*#__PURE__*/_react.default.createElement(_elementsCommentCount.default, {
114
167
  elementCommentsMap: element_comments_map,
115
- activeElement: activeElement,
168
+ activeElementIds: activeElementIds,
116
169
  editor: editor,
117
170
  onSelectElement: onSelectElement
118
171
  }), isShowComments && /*#__PURE__*/_react.default.createElement(_commentList.default, {
119
- activeElement: activeElement,
172
+ activeElementIds: activeElementIds,
120
173
  commentDetail: commentDetail,
121
- onSetCommentDetail: onSetCommentDetail
174
+ onSetCommentDetail: onSetCommentDetail,
175
+ isContextComment: isContextComment,
176
+ isClickedContextComment: isClickedContextComment,
177
+ setIsClickedContextComment: setIsClickedContextComment,
178
+ onSelectElement: onSelectElement,
179
+ commentedDom: commentedDomRef.current,
180
+ closeComment: hiddenComment,
181
+ editor: editor
122
182
  })));
123
183
  };
124
184
  var _default = exports.default = EditorComment;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.default = void 0;
8
8
  var _react = _interopRequireDefault(require("react"));
9
+ var _utils = require("../../utils");
9
10
  var _elementCommentCount = _interopRequireDefault(require("./element-comment-count"));
10
11
  require("./index.css");
11
12
  const ElementsCommentCount = _ref => {
@@ -18,14 +19,25 @@ const ElementsCommentCount = _ref => {
18
19
  if (!elementCommentsMap) return null;
19
20
  return /*#__PURE__*/_react.default.createElement("div", {
20
21
  className: "elements-comments-count"
21
- }, Object.keys(elementCommentsMap).map(elementId => {
22
- const comments = elementCommentsMap[elementId];
22
+ }, Object.keys(elementCommentsMap).map(originElementId => {
23
+ var _comments$0$detail$el, _comments$0$detail;
24
+ const comments = elementCommentsMap[originElementId];
23
25
  if (!Array.isArray(comments) || comments.length === 0) return null;
26
+ let elementId = originElementId;
27
+ const elementIdList = (_comments$0$detail$el = (_comments$0$detail = comments[0].detail) === null || _comments$0$detail === void 0 ? void 0 : _comments$0$detail.element_id_list) !== null && _comments$0$detail$el !== void 0 ? _comments$0$detail$el : [];
28
+ if (elementIdList.length > 1) {
29
+ const existedId = elementIdList.find(id => (0, _utils.getCommentElementById)(id, editor));
30
+ if (existedId) {
31
+ elementId = existedId;
32
+ } else {
33
+ return null;
34
+ }
35
+ }
24
36
  const unresolvedComment = comments.filter(item => !item.resolved);
25
37
  const unresolvedCommentCount = unresolvedComment.length;
26
38
  if (unresolvedCommentCount === 0) return null;
27
39
  return /*#__PURE__*/_react.default.createElement(_elementCommentCount.default, {
28
- key: elementId,
40
+ key: `${originElementId}-${elementId}`,
29
41
  elementId: elementId,
30
42
  isElementSelected: selectionElement && selectionElement.id === elementId,
31
43
  commentsCount: unresolvedCommentCount,
@@ -278,6 +278,31 @@
278
278
  overflow: hidden;
279
279
  }
280
280
 
281
+ .sdoc-comment-drawer .sdoc-comment-list-container .detail-context-comment {
282
+ align-items: start !important;
283
+ }
284
+
285
+ .sdoc-comment-drawer .sdoc-comment-list-container .detail-context-comment .sdoc-comment-quote {
286
+ padding-top: 1px;
287
+ }
288
+
289
+ .sdoc-comment-drawer .sdoc-comment-list-container .context-comment-item-selected-text-container {
290
+ padding: 16px 16px 0 16px;
291
+ color: #666;
292
+ display: flex;
293
+ }
294
+
295
+ .sdoc-comment-drawer .sdoc-comment-list-container .context-comment-item-selected-text-container .sdoc-comment-quote {
296
+ font-size: 12px;
297
+ padding-top: 1px;
298
+ }
299
+
300
+ .sdoc-comment-drawer .sdoc-comment-list-container .context-comment-item-selected-text-container .context-comment-items {
301
+ display: flex;
302
+ flex-direction: column;
303
+ font-size: 14px;
304
+ }
305
+
281
306
  .comments-panel-body__header .sdoc-comment-filter-dropdown.sdoc-dropdown-menu {
282
307
  border: 1px solid #dee3eb;
283
308
  }
@@ -4,9 +4,11 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.useCursorPosition = exports.getSelectionRange = exports.getElementCommentCountTop = exports.getCursorPosition = exports.getAvatarUrl = void 0;
7
+ exports.useCursorPosition = exports.updateElementsAttrs = exports.updateCommentedElementsAttrs = exports.getSelectionRange = exports.getSelectedElemIds = exports.getPrimaryElementId = exports.getElementCommentCountTop = exports.getDomById = exports.getCursorPosition = exports.getCommentedTextsByElementId = exports.getAvatarUrl = void 0;
8
+ var _slate = require("@seafile/slate");
8
9
  var _slateReact = require("@seafile/slate-react");
9
10
  var _context = _interopRequireDefault(require("../../context"));
11
+ var _core = require("../extension/core");
10
12
  var _useScrollContext = require("../hooks/use-scroll-context");
11
13
  const getSelectionRange = () => {
12
14
  if (window.getSelection) {
@@ -72,4 +74,111 @@ const getElementCommentCountTop = (editor, element, scrollTop) => {
72
74
  });
73
75
  return minY - 93 + scrollTop; // 100: header height(56) + toolbar height(37)
74
76
  };
75
- exports.getElementCommentCountTop = getElementCommentCountTop;
77
+ exports.getElementCommentCountTop = getElementCommentCountTop;
78
+ const getSelectedElemIds = editor => {
79
+ const {
80
+ selection
81
+ } = editor;
82
+ if (!selection) return;
83
+ const selectedElemId = [];
84
+ const nodeEntries = Array.from(_slate.Editor.nodes(editor, {
85
+ match: n => _slate.Element.isElement(n) && _slate.Editor.isBlock(editor, n),
86
+ mode: 'lowest'
87
+ }));
88
+ for (const [node] of nodeEntries) {
89
+ selectedElemId.push(node.id);
90
+ }
91
+ return selectedElemId;
92
+ };
93
+ exports.getSelectedElemIds = getSelectedElemIds;
94
+ const getCommentedTextsByElementId = (elementId, textCommentId) => {
95
+ const container = document.querySelector(`[data-id='${elementId}']`);
96
+ if (!container) return [];
97
+ let targetDoms = container.querySelectorAll(`.sdoc_comment_${textCommentId}`);
98
+ if (targetDoms.length === 0) {
99
+ targetDoms = container.querySelectorAll(`.removed_sdoc_comment_${textCommentId}`);
100
+ }
101
+ const texts = [];
102
+ targetDoms.forEach(dom => {
103
+ var _dom$textContent;
104
+ texts.push(((_dom$textContent = dom.textContent) === null || _dom$textContent === void 0 ? void 0 : _dom$textContent.trim()) || '');
105
+ });
106
+ return texts;
107
+ };
108
+ exports.getCommentedTextsByElementId = getCommentedTextsByElementId;
109
+ const getDomById = elementId => {
110
+ const container = document.querySelector(`[data-id='${elementId}']`);
111
+ if (!container) return [];
112
+ const lastCommentedDomWithMarks = container.querySelector('.comment');
113
+ return lastCommentedDomWithMarks;
114
+ };
115
+ exports.getDomById = getDomById;
116
+ const updateElementsAttrs = (activeElementIds, editor, text_comment_id) => {
117
+ if (Array.isArray(activeElementIds)) {
118
+ for (const elemId of activeElementIds) {
119
+ const dom = document.querySelectorAll(`[data-id="${elemId}"]`)[0];
120
+ if (!dom) continue;
121
+ const domNode = _slateReact.ReactEditor.toSlateNode(editor, dom);
122
+ const nodePath = (0, _core.findPath)(editor, domNode);
123
+ domNode.children.forEach((textNode, index) => {
124
+ if (textNode.comment) {
125
+ const textNodePath = [...nodePath, index];
126
+ _slate.Transforms.setNodes(editor, {
127
+ [`sdoc_comment_${text_comment_id}`]: true
128
+ }, {
129
+ at: textNodePath,
130
+ match: _slate.Text.isText,
131
+ split: true
132
+ });
133
+ }
134
+ });
135
+ }
136
+ }
137
+ };
138
+ exports.updateElementsAttrs = updateElementsAttrs;
139
+ const updateCommentedElementsAttrs = function (activeElementIds, editor, text_comment_id) {
140
+ let resolved = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
141
+ let isDeleteComment = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
142
+ if (Array.isArray(activeElementIds)) {
143
+ _slate.Editor.withoutNormalizing(editor, () => {
144
+ for (const elemId of activeElementIds) {
145
+ // const { element } = elem;
146
+ const dom = document.querySelector(`[data-id="${elemId}"]`);
147
+ if (!dom) continue;
148
+ const domNode = _slateReact.ReactEditor.toSlateNode(editor, dom);
149
+ const domNodePath = (0, _core.findPath)(editor, domNode);
150
+ domNode.children.forEach((child, index) => {
151
+ const childPath = [...domNodePath, index];
152
+ if (_slate.Text.isText(child) && `sdoc_comment_${text_comment_id}` in child) {
153
+ _slate.Transforms.unsetNodes(editor, [`sdoc_comment_${text_comment_id}`], {
154
+ at: childPath,
155
+ match: _slate.Text.isText
156
+ });
157
+ !isDeleteComment && _slate.Transforms.setNodes(editor, {
158
+ [`sdoc_comment_${text_comment_id}`]: resolved
159
+ }, {
160
+ at: childPath,
161
+ match: _slate.Text.isText
162
+ });
163
+ }
164
+ });
165
+ }
166
+ });
167
+ }
168
+ };
169
+ exports.updateCommentedElementsAttrs = updateCommentedElementsAttrs;
170
+ const getPrimaryElementId = detail => {
171
+ if (!detail) return null;
172
+ let elementId;
173
+ const {
174
+ element_id,
175
+ element_id_list = []
176
+ } = detail;
177
+ if (element_id_list.length > 0) {
178
+ elementId = element_id_list[0];
179
+ } else {
180
+ elementId = element_id;
181
+ }
182
+ return elementId;
183
+ };
184
+ exports.getPrimaryElementId = getPrimaryElementId;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.sortCommentList = exports.initElementCommentsMap = exports.initCommentsInfo = exports.initCommentList = exports.formatCommentsData = exports.commentReducer = void 0;
8
8
  var _deepCopy = _interopRequireDefault(require("deep-copy"));
9
+ var _helper = require("../helper");
9
10
  const formatCommentsData = comments => {
10
11
  const formatComments = [];
11
12
  const dupComments = (0, _deepCopy.default)(comments);
@@ -29,9 +30,7 @@ const initElementCommentsMap = comments => {
29
30
  const formatComments = formatCommentsData(comments);
30
31
  for (let i = 0; i < formatComments.length; i++) {
31
32
  const item = formatComments[i];
32
- const {
33
- element_id
34
- } = item.detail;
33
+ const element_id = (0, _helper.getPrimaryElementId)(item.detail);
35
34
  if (!elementCommentsMap[element_id]) {
36
35
  elementCommentsMap[element_id] = [];
37
36
  }
@@ -49,7 +49,8 @@ const INTERNAL_EVENT = exports.INTERNAL_EVENT = {
49
49
  RESIZE_ARTICLE: 'resize_article',
50
50
  ON_VIDEO_FILES_UPLOADED: 'on_video_files_uploaded',
51
51
  RELOAD_COMMENT: 'reload_comment',
52
- ASK_AI: 'ask_ai'
52
+ ASK_AI: 'ask_ai',
53
+ ADD_CONTEXT_COMMENT: 'add_context_comment'
53
54
  };
54
55
  const REVISION_DIFF_KEY = exports.REVISION_DIFF_KEY = 'diff';
55
56
  const REVISION_DIFF_VALUE = exports.REVISION_DIFF_VALUE = '1';
@@ -122,12 +122,12 @@ const SdocEditor = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
122
122
  const eventBus = _basicSdk.EventBus.getInstance();
123
123
  eventBus.subscribe(_constants.EXTERNAL_EVENT.REFRESH_DOCUMENT, onRefreshDocument);
124
124
 
125
- // Remove aiMarks on special conditions like unexpected exit or refresh page using AI
126
- const hasAIMark = !_slate.Editor.nodes(validEditor, {
125
+ // Remove Marks on special conditions like unexpected exit or refresh page using AI or context comment
126
+ const hasSpecialMark = !_slate.Editor.nodes(validEditor, {
127
127
  at: [],
128
- match: n => _slate.Text.isText(n) && n.sdoc_ai === true
128
+ match: n => _slate.Text.isText(n) && (n.sdoc_ai === true || n.comment === true)
129
129
  }).next().done;
130
- if (hasAIMark) {
130
+ if (hasSpecialMark) {
131
131
  (0, _helpers.removeMarks)(validEditor);
132
132
  }
133
133
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -12,7 +12,7 @@ var _reactI18next = require("react-i18next");
12
12
  var _reactstrap = require("reactstrap");
13
13
  var _classnames = _interopRequireDefault(require("classnames"));
14
14
  var _tooltip = _interopRequireDefault(require("../../../../components/tooltip"));
15
- var _utils = require("../../../../utils");
15
+ var _localStorageUtils = _interopRequireDefault(require("../../../utils/local-storage-utils"));
16
16
  var _mouseEvent = require("../../../utils/mouse-event");
17
17
  var _constants = require("../../constants");
18
18
  var _colorItem = _interopRequireDefault(require("./color-item"));
@@ -37,7 +37,7 @@ const ColorMenu = _ref => {
37
37
  } = _ref;
38
38
  const popoverRef = (0, _react.useRef)(null);
39
39
  const moreColorsPopoverRef = (0, _react.useRef)(null);
40
- const [recentUsedColors, setRecentUsedColors] = (0, _react.useState)(_utils.LocalStorage.getItem(recentUsedColorsKey, _constants.DEFAULT_RECENT_USED_LIST));
40
+ const [recentUsedColors, setRecentUsedColors] = (0, _react.useState)(_localStorageUtils.default.getItem(recentUsedColorsKey, _constants.DEFAULT_RECENT_USED_LIST));
41
41
  const [isShowMenu, setMenuShow] = (0, _react.useState)(false);
42
42
  const [isPickerShow, setPickerShow] = (0, _react.useState)(false);
43
43
  const onSetColor = (0, _react.useCallback)(function (color) {
@@ -48,7 +48,7 @@ const ColorMenu = _ref => {
48
48
  if (validColor !== '' && recentUsedColors[0] !== validColor) {
49
49
  let newRecentUsedColors = recentUsedColors.slice(0, 9);
50
50
  newRecentUsedColors.unshift(validColor);
51
- _utils.LocalStorage.setItem(recentUsedColorsKey, newRecentUsedColors);
51
+ _localStorageUtils.default.setItem(recentUsedColorsKey, newRecentUsedColors);
52
52
  setRecentUsedColors(newRecentUsedColors);
53
53
  }
54
54
  updateLastUsedColor && updateLastUsedColor(validColor);
@@ -14,10 +14,11 @@ var _classnames = _interopRequireDefault(require("classnames"));
14
14
  var _toast = _interopRequireDefault(require("../../../../components/toast"));
15
15
  var _constants = require("../../../../constants");
16
16
  var _context = _interopRequireDefault(require("../../../../context"));
17
- var _utils = require("../../../../utils");
18
17
  var _constants2 = require("../../../constants");
18
+ var _commonUtils = require("../../../utils/common-utils");
19
19
  var _debounce = _interopRequireDefault(require("../../../utils/debounce"));
20
20
  var _eventBus = _interopRequireDefault(require("../../../utils/event-bus"));
21
+ var _localStorageUtils = _interopRequireDefault(require("../../../utils/local-storage-utils"));
21
22
  var _constants3 = require("../../constants");
22
23
  var _helpers = require("../../plugins/sdoc-link/helpers");
23
24
  var _helpers2 = require("../select-file-dialog/helpers");
@@ -98,9 +99,9 @@ const FileLinkInsertDialog = _ref => {
98
99
  }, [getPosition]);
99
100
  const getHistoryFiles = (0, _react.useCallback)(isCalculatedByFiles => {
100
101
  const getItemKey = 'sdoc-recent-files';
101
- let files = _utils.LocalStorage.getItem(getItemKey) || [];
102
+ let files = _localStorageUtils.default.getItem(getItemKey) || [];
102
103
  if (isCalculatedByFiles) {
103
- const newFiles = (0, _utils.getMaximumCapacity)(files);
104
+ const newFiles = (0, _commonUtils.getMaximumCapacity)(files);
104
105
  // Can accommodate all without showing more operations
105
106
  if (files.length <= newFiles.length) {
106
107
  setHiddenMoreMenu(true);
@@ -166,7 +167,7 @@ const FileLinkInsertDialog = _ref => {
166
167
  setNewFileName(searchText);
167
168
 
168
169
  // Cannot be found if the search is less than three characters.
169
- if ((0, _utils.isEnglish)(searchText.trim()) && searchText.length < 3) {
170
+ if ((0, _commonUtils.isEnglish)(searchText.trim()) && searchText.length < 3) {
170
171
  setFiles([]);
171
172
  setHeader(t('Enter_more_character_start_search'));
172
173
  return;
@@ -13,9 +13,10 @@ var _slateReact = require("@seafile/slate-react");
13
13
  var _classnames = _interopRequireDefault(require("classnames"));
14
14
  var _lodash = _interopRequireDefault(require("lodash.throttle"));
15
15
  var _constants = require("../../../../constants");
16
- var _utils = require("../../../../utils");
17
16
  var _constants2 = require("../../../constants");
17
+ var _commonUtils = require("../../../utils/common-utils");
18
18
  var _eventBus = _interopRequireDefault(require("../../../utils/event-bus"));
19
+ var _localStorageUtils = _interopRequireDefault(require("../../../utils/local-storage-utils"));
19
20
  var _helpers = require("../../plugins/sdoc-link/helpers");
20
21
  var _helpers2 = require("../../plugins/wiki-link/helpers");
21
22
  require("./style.css");
@@ -91,9 +92,9 @@ const WikiFileLinkInsertDialog = _ref => {
91
92
  getPosition();
92
93
  }, 100);
93
94
  const getHistoryFiles = (0, _react.useCallback)(isCalculatedByFiles => {
94
- let files = (0, _utils.getLocalStorageFiles)(_utils.LocalStorage.getItem('wiki-recent-files') || []);
95
+ let files = (0, _commonUtils.getLocalStorageFiles)(_localStorageUtils.default.getItem('wiki-recent-files') || []);
95
96
  if (isCalculatedByFiles) {
96
- const newFiles = (0, _utils.getMaximumCapacity)(files);
97
+ const newFiles = (0, _commonUtils.getMaximumCapacity)(files);
97
98
  // Can accommodate all without showing more operations
98
99
  if (files.length <= newFiles.length) {
99
100
  setHiddenMoreMenu(true);
@@ -202,7 +203,7 @@ const WikiFileLinkInsertDialog = _ref => {
202
203
  }, [closeDialog, editor, element]);
203
204
  const onShowMoreWiki = (0, _react.useCallback)(e => {
204
205
  e.stopPropagation();
205
- const recentFiles = (0, _utils.getLocalStorageFiles)(_utils.LocalStorage.getItem('wiki-recent-files') || []);
206
+ const recentFiles = (0, _commonUtils.getLocalStorageFiles)(_localStorageUtils.default.getItem('wiki-recent-files') || []);
206
207
  setFiles(recentFiles);
207
208
  setHiddenMoreMenu(true);
208
209
  }, []);
@@ -1,13 +1,11 @@
1
1
  "use strict";
2
2
 
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
3
  Object.defineProperty(exports, "__esModule", {
5
4
  value: true
6
5
  });
7
6
  exports.someNode = exports.isTopLevelListItem = exports.isTextNode = exports.isStartPoint = exports.isSelectionAtBlockStart = exports.isSelectionAtBlockEnd = exports.isRangeInSameBlock = exports.isRangeAcrossBlocks = exports.isMultiLevelList = exports.isMiddlePoint = exports.isLastNode = exports.isLastChild = exports.isHasImg = exports.isFirstChild = exports.isEndPoint = exports.isEmptyArticle = exports.isCursorAtBlockStart = exports.isCurrentLineHasText = exports.isCurrentLineEmpty = exports.isContainsVoidElement = exports.isBlockTextEmptyAfterSelection = exports.isBlockAboveEmpty = exports.isAncestorEmpty = exports.getTopLevelBlockNode = exports.getStartPoint = exports.getSelectedNodeEntryByType = exports.getSelectedNodeByTypes = exports.getSelectedNodeByType = exports.getSelectedElems = exports.getQueryOptions = exports.getPreviousPath = exports.getPrevNode = exports.getPointBefore = exports.getParentNode = exports.getNodes = exports.getNodeType = exports.getNodeEntries = exports.getNodeById = exports.getNode = exports.getNextSiblingNodes = exports.getNextNode = exports.getLastChildPath = exports.getLastChild = exports.getEndPoint = exports.getEditorString = exports.getDeepInlineChildren = exports.getCurrentNode = exports.getCommonNode = exports.getChildren = exports.getAboveNode = exports.getAboveBlockNode = exports.findPath = exports.findNode = exports.findDescendant = void 0;
8
7
  var _slate = require("@seafile/slate");
9
8
  var _slateReact = require("@seafile/slate-react");
10
- var _objectUtils = _interopRequireDefault(require("../../../utils/object-utils"));
11
9
  var _constants = require("../../constants");
12
10
  var _utils = require("../utils");
13
11
  // options
@@ -377,7 +375,8 @@ const findDescendant = (editor, options) => {
377
375
  exports.findDescendant = findDescendant;
378
376
  const isTextNode = node => {
379
377
  if (!node) return false;
380
- if (!_objectUtils.default.hasProperty(node, 'children') && _objectUtils.default.hasProperty(node, 'text')) return true;
378
+ if (_slate.Text.isText(node)) return true;
379
+ return false;
381
380
  };
382
381
  exports.isTextNode = isTextNode;
383
382
  const isLastChild = (nodeEntry, childPath) => {
@@ -4,10 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.Placeholder = Placeholder;
8
7
  exports.match = exports.generateEmptyElement = exports.generateDefaultText = exports.generateDefaultParagraph = void 0;
9
- var _react = _interopRequireDefault(require("react"));
10
- var _reactI18next = require("react-i18next");
11
8
  var _slugid = _interopRequireDefault(require("slugid"));
12
9
  var _constants = require("../../constants");
13
10
  const match = (node, path, predicate) => {
@@ -50,29 +47,4 @@ const generateEmptyElement = function (type) {
50
47
  children: [generateDefaultText(text)]
51
48
  };
52
49
  };
53
- exports.generateEmptyElement = generateEmptyElement;
54
- function Placeholder(props) {
55
- const {
56
- title,
57
- top = 5
58
- } = props;
59
- const {
60
- t
61
- } = (0, _reactI18next.useTranslation)('sdoc-editor');
62
- return /*#__PURE__*/_react.default.createElement("span", {
63
- contentEditable: "false",
64
- suppressContentEditableWarning: true,
65
- style: {
66
- position: 'absolute',
67
- top: `${top}px`,
68
- color: 'rgba(191,191,191,1)',
69
- pointerEvents: 'none',
70
- width: '100%',
71
- maxWidth: '100%',
72
- display: 'block',
73
- userSelect: 'none',
74
- textDecoration: 'none',
75
- left: '1px'
76
- }
77
- }, t(title));
78
- }
50
+ exports.generateEmptyElement = generateEmptyElement;
@@ -17,9 +17,9 @@ function AIIcon(_ref) {
17
17
  const {
18
18
  t
19
19
  } = (0, _reactI18next.useTranslation)('sdoc-editor');
20
- const clazznames = (0, _classnames.default)('sdoc-ask-ai-icon', className);
20
+ const classnames = (0, _classnames.default)('sdoc-ask-ai-icon', className);
21
21
  return /*#__PURE__*/_react.default.createElement("img", {
22
- className: clazznames,
22
+ className: classnames,
23
23
  src: _sdocAskAi.default,
24
24
  alt: t('Ask_AI')
25
25
  });
@@ -13,6 +13,10 @@ const removeMarks = editor => {
13
13
  at: [],
14
14
  match: n => _slate.Text.isText(n) && n.sdoc_ai === true
15
15
  });
16
+ _slate.Transforms.unsetNodes(editor, 'comment', {
17
+ at: [],
18
+ match: n => _slate.Text.isText(n) && n.comment === true
19
+ });
16
20
  if (selection) {
17
21
  _slate.Transforms.select(editor, selection);
18
22
  } else {