@seafile/sdoc-editor 1.0.205 → 1.0.206-test-5.0.20

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 (32) hide show
  1. package/dist/basic-sdk/comment/components/comment-item-content.js +5 -3
  2. package/dist/basic-sdk/extension/commons/file-insert-dialog/index.js +1 -1
  3. package/dist/basic-sdk/extension/commons/insert-element-dialog/index.js +21 -0
  4. package/dist/basic-sdk/extension/commons/select-file-dialog/helpers.js +8 -3
  5. package/dist/basic-sdk/extension/commons/select-file-dialog/index.js +50 -8
  6. package/dist/basic-sdk/extension/commons/select-file-dialog/local-files/index.css +1 -0
  7. package/dist/basic-sdk/extension/commons/select-file-dialog/local-files/index.js +6 -2
  8. package/dist/basic-sdk/extension/constants/element-type.js +2 -1
  9. package/dist/basic-sdk/extension/constants/index.js +2 -1
  10. package/dist/basic-sdk/extension/core/queries/index.js +18 -14
  11. package/dist/basic-sdk/extension/plugins/callout/helper.js +1 -1
  12. package/dist/basic-sdk/extension/plugins/font/helpers.js +4 -0
  13. package/dist/basic-sdk/extension/plugins/sdoc-link/helpers.js +3 -3
  14. package/dist/basic-sdk/extension/plugins/sdoc-link/render/render-elem.js +1 -1
  15. package/dist/basic-sdk/extension/plugins/text-align/helpers.js +2 -0
  16. package/dist/basic-sdk/extension/plugins/video/dialog/add-video-link-dialog/index.js +99 -0
  17. package/dist/basic-sdk/extension/plugins/video/helpers.js +61 -8
  18. package/dist/basic-sdk/extension/plugins/video/index.css +4 -3
  19. package/dist/basic-sdk/extension/plugins/video/menu/index.js +24 -1
  20. package/dist/basic-sdk/extension/plugins/video/render-elem.js +20 -7
  21. package/dist/constants/index.js +1 -0
  22. package/package.json +1 -1
  23. package/public/locales/cs/sdoc-editor.json +6 -2
  24. package/public/locales/de/sdoc-editor.json +311 -307
  25. package/public/locales/en/sdoc-editor.json +6 -2
  26. package/public/locales/es/sdoc-editor.json +6 -2
  27. package/public/locales/es_AR/sdoc-editor.json +6 -2
  28. package/public/locales/es_MX/sdoc-editor.json +6 -2
  29. package/public/locales/fr/sdoc-editor.json +6 -2
  30. package/public/locales/it/sdoc-editor.json +6 -2
  31. package/public/locales/ru/sdoc-editor.json +7 -3
  32. package/public/locales/zh_CN/sdoc-editor.json +5 -1
@@ -14,7 +14,7 @@ var _commentEditor = _interopRequireDefault(require("./comment-editor"));
14
14
  var _tooltip = _interopRequireDefault(require("../../../components/tooltip"));
15
15
  var _notificationHooks = require("../hooks/notification-hooks");
16
16
  var _mdToHtml = _interopRequireDefault(require("../../../slate-convert/md-to-html"));
17
- const CommentItem = _ref => {
17
+ const CommentItemContent = _ref => {
18
18
  let {
19
19
  isActive,
20
20
  container,
@@ -96,7 +96,9 @@ const CommentItem = _ref => {
96
96
  className: "name"
97
97
  }, comment.user_name), /*#__PURE__*/_react.default.createElement("span", {
98
98
  className: "time"
99
- }, (0, _dayjs.default)(comment.updated_at).format('MM-DD HH:mm')))), isUnseen && !isActive && /*#__PURE__*/_react.default.createElement("span", {
99
+ }, (0, _dayjs.default)(comment.updated_at).format('MM-DD HH:mm'), (comment === null || comment === void 0 ? void 0 : comment.resolved) && /*#__PURE__*/_react.default.createElement("span", {
100
+ className: "comment-success-resolved sdocfont sdoc-mark-as-resolved"
101
+ })))), isUnseen && !isActive && /*#__PURE__*/_react.default.createElement("span", {
100
102
  className: "sdoc-unread-message-tip"
101
103
  }), isActive && /*#__PURE__*/_react.default.createElement("div", {
102
104
  className: "d-flex comment-item-operation-wrapper"
@@ -149,4 +151,4 @@ const CommentItem = _ref => {
149
151
  setIsEditing: setIsEditing
150
152
  }));
151
153
  };
152
- var _default = exports.default = (0, _reactI18next.withTranslation)('sdoc-editor')(CommentItem);
154
+ var _default = exports.default = (0, _reactI18next.withTranslation)('sdoc-editor')(CommentItemContent);
@@ -252,7 +252,7 @@ const FileLinkInsertDialog = _ref => {
252
252
  }
253
253
  }, /*#__PURE__*/_react.default.createElement("img", {
254
254
  className: "file-item-img",
255
- src: (0, _helpers2.sdocFileIcon)(),
255
+ src: (0, _helpers2.getSdocFileIcon)(),
256
256
  alt: ""
257
257
  }), /*#__PURE__*/_react.default.createElement("span", {
258
258
  className: "file-item-name"
@@ -23,6 +23,7 @@ var _index4 = _interopRequireDefault(require("../../../../components/toast/index
23
23
  var _index5 = require("../../plugins/video/constants/index.js");
24
24
  var _constants3 = require("../../../../basic-sdk/constants");
25
25
  var _index6 = _interopRequireDefault(require("../../plugins/ai/ai-module/index.js"));
26
+ var _index7 = _interopRequireDefault(require("../../plugins/video/dialog/add-video-link-dialog/index.js"));
26
27
  const InsertElementDialog = _ref => {
27
28
  let {
28
29
  editor
@@ -32,6 +33,7 @@ const InsertElementDialog = _ref => {
32
33
  const [insertPosition, setInsertPosition] = (0, _react.useState)(_constants2.INSERT_POSITION.CURRENT);
33
34
  const [slateNode, setSlateNode] = (0, _react.useState)(null);
34
35
  const [insertLinkCallback, setInsertLinkCallback] = (0, _react.useState)(null);
36
+ const [insertVideoCallback, setInsertVideoCallback] = (0, _react.useState)(null);
35
37
  const [validEditor, setValidEditor] = (0, _react.useState)(editor);
36
38
  const [linkTitle, setLinkTitle] = (0, _react.useState)('');
37
39
  const [handleSubmit, setHandleSubmit] = (0, _react.useState)(() => void 0);
@@ -90,6 +92,7 @@ const InsertElementDialog = _ref => {
90
92
  slateNode,
91
93
  insertFileLinkCallback,
92
94
  insertSdocFileLinkCallback,
95
+ insertVideo,
93
96
  editor: paramEditor,
94
97
  linkTitle,
95
98
  // link shortcut wrapping link
@@ -103,6 +106,9 @@ const InsertElementDialog = _ref => {
103
106
  insertSdocFileLinkCallback,
104
107
  insertFileLinkCallback
105
108
  });
109
+ setInsertVideoCallback({
110
+ insertVideo
111
+ });
106
112
  setLinkTitle(linkTitle);
107
113
  setHandleSubmit(handleSubmit);
108
114
  // Apply for comment editor, as it has a different editor instance
@@ -124,6 +130,7 @@ const InsertElementDialog = _ref => {
124
130
  setElement('');
125
131
  setDialogType('');
126
132
  setInsertLinkCallback(null);
133
+ setInsertVideoCallback(null);
127
134
  setValidEditor(null);
128
135
  setLinkTitle('');
129
136
  }, []);
@@ -169,6 +176,20 @@ const InsertElementDialog = _ref => {
169
176
  };
170
177
  return /*#__PURE__*/_react.default.createElement(_index.default, fileLinkProps);
171
178
  }
179
+ case _constants2.ELEMENT_TYPE.VIDEO:
180
+ {
181
+ const videoProps = {
182
+ editor: validEditor,
183
+ dialogType,
184
+ insertVideoCallback,
185
+ closeDialog
186
+ };
187
+ return /*#__PURE__*/_react.default.createElement(_index.default, videoProps);
188
+ }
189
+ case _constants2.ELEMENT_TYPE.VIDEO_LINK:
190
+ {
191
+ return /*#__PURE__*/_react.default.createElement(_index7.default, props);
192
+ }
172
193
  case _constants2.LOCAL_IMAGE:
173
194
  {
174
195
  return /*#__PURE__*/_react.default.createElement("input", {
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.sdocFileIcon = exports.addDataToTree = void 0;
7
+ exports.getVideoFileIcon = exports.getSdocFileIcon = exports.addDataToTree = void 0;
8
8
  var _context = _interopRequireDefault(require("../../../../context"));
9
9
  const addDataToTree = (treeData, indexId, childrenData, path) => {
10
10
  for (let i = 0; i < treeData.length; i++) {
@@ -24,8 +24,13 @@ const addDataToTree = (treeData, indexId, childrenData, path) => {
24
24
  return treeData;
25
25
  };
26
26
  exports.addDataToTree = addDataToTree;
27
- const sdocFileIcon = () => {
27
+ const getSdocFileIcon = () => {
28
28
  const server = _context.default.getSetting('serviceUrl');
29
29
  return `${server}/media/img/file/256/sdoc.png`;
30
30
  };
31
- exports.sdocFileIcon = sdocFileIcon;
31
+ exports.getSdocFileIcon = getSdocFileIcon;
32
+ const getVideoFileIcon = () => {
33
+ const server = _context.default.getSetting('serviceUrl');
34
+ return `${server}/media/img/file/256/video.png`;
35
+ };
36
+ exports.getVideoFileIcon = getVideoFileIcon;
@@ -21,9 +21,9 @@ const SelectSdocFileDialog = _ref => {
21
21
  editor,
22
22
  dialogType,
23
23
  closeDialog,
24
- insertLinkCallback
24
+ insertLinkCallback,
25
+ insertVideoCallback
25
26
  } = _ref;
26
- const modalTitle = dialogType === _constants.ELEMENT_TYPE.FILE_LINK ? 'Select_file' : 'Select_sdoc_document';
27
27
  const {
28
28
  t
29
29
  } = (0, _reactI18next.useTranslation)('sdoc-editor');
@@ -31,6 +31,20 @@ const SelectSdocFileDialog = _ref => {
31
31
  const [temSearchContent, setTemSearchContent] = (0, _react.useState)('');
32
32
  const [searchContent, setSearchContent] = (0, _react.useState)('');
33
33
  const [isOpenSearch, setIsOpenSearch] = (0, _react.useState)(false);
34
+ let modalTitle;
35
+ switch (dialogType) {
36
+ case _constants.ELEMENT_TYPE.FILE_LINK:
37
+ modalTitle = 'Select_file';
38
+ break;
39
+ case _constants.ELEMENT_TYPE.SDOC_LINK:
40
+ modalTitle = 'Select_sdoc_document';
41
+ break;
42
+ case _constants.ELEMENT_TYPE.VIDEO:
43
+ modalTitle = 'Select_video_file';
44
+ break;
45
+ default:
46
+ break;
47
+ }
34
48
  const onSelectedFile = (0, _react.useCallback)(fileInfo => {
35
49
  setCurrentSelectedFile(fileInfo);
36
50
  }, []);
@@ -38,13 +52,33 @@ const SelectSdocFileDialog = _ref => {
38
52
  const {
39
53
  insertFileLinkCallback,
40
54
  insertSdocFileLinkCallback
41
- } = insertLinkCallback;
42
- if (dialogType === _constants.ELEMENT_TYPE.FILE_LINK) {
43
- insertFileLinkCallback && insertFileLinkCallback(editor, fileInfo.name, fileInfo.file_uuid);
44
- } else {
45
- insertSdocFileLinkCallback && insertSdocFileLinkCallback(editor, fileInfo.name, fileInfo.file_uuid);
55
+ } = insertLinkCallback || {};
56
+ const {
57
+ insertVideo
58
+ } = insertVideoCallback || {};
59
+ switch (dialogType) {
60
+ case _constants.ELEMENT_TYPE.FILE_LINK:
61
+ insertFileLinkCallback && insertFileLinkCallback(editor, fileInfo.name, fileInfo.file_uuid);
62
+ break;
63
+ case _constants.ELEMENT_TYPE.SDOC_LINK:
64
+ insertSdocFileLinkCallback && insertSdocFileLinkCallback(editor, fileInfo.name, fileInfo.file_uuid);
65
+ break;
66
+ case _constants.ELEMENT_TYPE.VIDEO:
67
+ const repoID = _context.default.getSetting('repoID');
68
+ const fileServerRoot = _context.default.getSetting('fileServerRoot');
69
+ console.log(repoID, fileServerRoot);
70
+ // const { fileServerRoot } = window.app.config;
71
+ // Get seafile's video download url as src
72
+ const url = `${fileServerRoot}repos/${repoID}/files${fileInfo.path}/?op=download`;
73
+ const encodedUrl = encodeURI(url);
74
+ insertVideo && insertVideo(editor, [{
75
+ name: fileInfo.name
76
+ }], [encodedUrl]);
77
+ break;
78
+ default:
79
+ break;
46
80
  }
47
- }, [insertLinkCallback, dialogType, editor]);
81
+ }, [insertLinkCallback, insertVideoCallback, dialogType, editor]);
48
82
  const onSubmit = (0, _react.useCallback)(() => {
49
83
  if (!currentSelectedFile) return;
50
84
  const {
@@ -53,6 +87,14 @@ const SelectSdocFileDialog = _ref => {
53
87
  let fileInfo = {
54
88
  ...currentSelectedFile
55
89
  };
90
+
91
+ // Insert video element in sdoc
92
+ if (dialogType === _constants.ELEMENT_TYPE.VIDEO) {
93
+ insertFile(fileInfo);
94
+ closeDialog();
95
+ return;
96
+ }
97
+
56
98
  // File has no id
57
99
  if (!file_uuid || file_uuid === '') {
58
100
  _context.default.getSdocLocalFileId(currentSelectedFile.path).then(res => {
@@ -36,6 +36,7 @@
36
36
  left: 0;
37
37
  }
38
38
 
39
+ .sdoc-file-icon-container .video-file-img,
39
40
  .sdoc-file-icon-container .sdoc-file-img {
40
41
  position: absolute;
41
42
  width: 21.6px;
@@ -155,7 +155,7 @@ const LocalFiles = _ref => {
155
155
  className: "sdoc-folder-children"
156
156
  }, ((_item$children = item.children) === null || _item$children === void 0 ? void 0 : _item$children.length) === 0 && /*#__PURE__*/_react.default.createElement("div", {
157
157
  className: "sdoc-folder-children-empty"
158
- }, `(${t('Empty')})`), ((_item$children2 = item.children) === null || _item$children2 === void 0 ? void 0 : _item$children2.length) > 0 && renderFileTree(item.children))), type === 'file' && /*#__PURE__*/_react.default.createElement("div", {
158
+ }, `(${t('Empty')})`), ((_item$children2 = item.children) === null || _item$children2 === void 0 ? void 0 : _item$children2.length) > 0 && renderFileTree(item.children))), ['file', 'video'].includes(type) && /*#__PURE__*/_react.default.createElement("div", {
159
159
  className: (0, _classnames.default)('sdoc-file-info', {
160
160
  'active': selected
161
161
  }),
@@ -170,7 +170,11 @@ const LocalFiles = _ref => {
170
170
  })
171
171
  }), fileType === 'sdoc' && /*#__PURE__*/_react.default.createElement("img", {
172
172
  className: "sdoc-file-img",
173
- src: (0, _helpers.sdocFileIcon)(),
173
+ src: (0, _helpers.getSdocFileIcon)(),
174
+ alt: ""
175
+ }), fileType === 'video' && /*#__PURE__*/_react.default.createElement("img", {
176
+ className: "video-file-img",
177
+ src: (0, _helpers.getVideoFileIcon)(),
174
178
  alt: ""
175
179
  })), /*#__PURE__*/_react.default.createElement("span", {
176
180
  className: "sdoc-file-name"
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.WIKI_LINK = exports.VIDEO = exports.UNORDERED_LIST = exports.TWO_COLUMN = exports.TOP_LEVEL_TYPES = exports.TITLE = exports.THREE_COLUMN = exports.TABLE_ROW = exports.TABLE_CELL = exports.TABLE = exports.SUBTITLE = exports.SEATABLE_TABLE = exports.SEATABLE_COLUMN = exports.SDOC_LINK = exports.QUICK_INSERT = exports.PARAGRAPH = exports.ORDERED_LIST = exports.MULTI_COLUMN = exports.MENTION_TEMP = exports.MENTION = exports.LIST_ITEM = exports.LINK = exports.INLINE_LEVEL_TYPES = exports.IMAGE_BLOCK = exports.IMAGE = exports.HEADER6 = exports.HEADER5 = exports.HEADER4 = exports.HEADER3 = exports.HEADER2 = exports.HEADER1 = exports.HEADER = exports.FOUR_COLUMN = exports.FONT_SIZE_REDUCE = exports.FONT_SIZE_INCREASE = exports.FONT_SIZE = exports.FIVE_COLUMN = exports.FILE_LINK_INSET_INPUT_TEMP = exports.FILE_LINK = exports.COLUMN = exports.CODE_LINE = exports.CODE_BLOCK = exports.CHECK_LIST_ITEM = exports.CALL_OUT = exports.BLOCKQUOTE = exports.ASK_AI = void 0;
6
+ exports.WIKI_LINK = exports.VIDEO_LINK = exports.VIDEO = exports.UNORDERED_LIST = exports.TWO_COLUMN = exports.TOP_LEVEL_TYPES = exports.TITLE = exports.THREE_COLUMN = exports.TABLE_ROW = exports.TABLE_CELL = exports.TABLE = exports.SUBTITLE = exports.SEATABLE_TABLE = exports.SEATABLE_COLUMN = exports.SDOC_LINK = exports.QUICK_INSERT = exports.PARAGRAPH = exports.ORDERED_LIST = exports.MULTI_COLUMN = exports.MENTION_TEMP = exports.MENTION = exports.LIST_ITEM = exports.LINK = exports.INLINE_LEVEL_TYPES = exports.IMAGE_BLOCK = exports.IMAGE = exports.HEADER6 = exports.HEADER5 = exports.HEADER4 = exports.HEADER3 = exports.HEADER2 = exports.HEADER1 = exports.HEADER = exports.FOUR_COLUMN = exports.FONT_SIZE_REDUCE = exports.FONT_SIZE_INCREASE = exports.FONT_SIZE = exports.FIVE_COLUMN = exports.FILE_LINK_INSET_INPUT_TEMP = exports.FILE_LINK = exports.COLUMN = exports.CODE_LINE = exports.CODE_BLOCK = exports.CHECK_LIST_ITEM = exports.CALL_OUT = exports.BLOCKQUOTE = exports.ASK_AI = void 0;
7
7
  const BLOCKQUOTE = exports.BLOCKQUOTE = 'blockquote';
8
8
  const TITLE = exports.TITLE = 'title';
9
9
  const SUBTITLE = exports.SUBTITLE = 'subtitle';
@@ -42,6 +42,7 @@ const MENTION = exports.MENTION = 'mention';
42
42
  const MENTION_TEMP = exports.MENTION_TEMP = 'mention_temp';
43
43
  const FILE_LINK_INSET_INPUT_TEMP = exports.FILE_LINK_INSET_INPUT_TEMP = 'file_link_insert_input_temp';
44
44
  const QUICK_INSERT = exports.QUICK_INSERT = 'quick_insert';
45
+ const VIDEO_LINK = exports.VIDEO_LINK = 'video_link';
45
46
  const SEATABLE_COLUMN = exports.SEATABLE_COLUMN = 'seatable_column';
46
47
  const SEATABLE_TABLE = exports.SEATABLE_TABLE = 'seatable_table';
47
48
  const ASK_AI = exports.ASK_AI = 'ask_ai';
@@ -532,7 +532,8 @@ const LIST_ITEM_SUPPORTED_TRANSFORMATION = exports.LIST_ITEM_SUPPORTED_TRANSFORM
532
532
  const ADD_POSITION_OFFSET_TYPE = exports.ADD_POSITION_OFFSET_TYPE = [_elementType.PARAGRAPH, _elementType.SUBTITLE, _elementType.HEADER1, _elementType.HEADER2, _elementType.HEADER3, _elementType.HEADER4, _elementType.HEADER5, _elementType.HEADER6, _elementType.CHECK_LIST_ITEM, _elementType.IMAGE_BLOCK];
533
533
  const FILE_TYPE = exports.FILE_TYPE = {
534
534
  [_elementType.FILE_LINK]: 'file',
535
- [_elementType.SDOC_LINK]: 'sdoc'
535
+ [_elementType.SDOC_LINK]: 'sdoc',
536
+ [_elementType.VIDEO]: 'video'
536
537
  };
537
538
  const SUPPORTED_SIDE_OPERATION_TYPE = exports.SUPPORTED_SIDE_OPERATION_TYPE = [_elementType.PARAGRAPH, _elementType.SUBTITLE, _elementType.HEADER1, _elementType.HEADER2, _elementType.HEADER3, _elementType.HEADER4, _elementType.HEADER5, _elementType.HEADER6, _elementType.CHECK_LIST_ITEM, _elementType.CODE_BLOCK, _elementType.TABLE, _elementType.BLOCKQUOTE, _elementType.CALL_OUT, _elementType.IMAGE_BLOCK, _elementType.VIDEO, _elementType.SEATABLE_TABLE, _elementType.MULTI_COLUMN];
538
539
  const MOUSE_ENTER_EVENT_DISABLED_MAP = exports.MOUSE_ENTER_EVENT_DISABLED_MAP = {
@@ -424,20 +424,24 @@ const isRangeAcrossBlocks = function (editor) {
424
424
  at,
425
425
  ...options
426
426
  } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
427
- if (!at) at = editor.selection;
428
- if (!at) return;
429
- const [start, end] = _slate.Range.edges(at);
430
- const startBlock = getAboveBlockNode(editor, {
431
- at: start,
432
- ...options
433
- });
434
- const endBlock = getAboveBlockNode(editor, {
435
- at: end,
436
- ...options
437
- });
438
- if (!startBlock && !endBlock) return;
439
- if (!startBlock || !endBlock) return true;
440
- return !_slate.Path.equals(startBlock[1], endBlock[1]);
427
+ try {
428
+ if (!at) at = editor.selection;
429
+ if (!at) return;
430
+ const [start, end] = _slate.Range.edges(at);
431
+ const startBlock = getAboveBlockNode(editor, {
432
+ at: start,
433
+ ...options
434
+ });
435
+ const endBlock = getAboveBlockNode(editor, {
436
+ at: end,
437
+ ...options
438
+ });
439
+ if (!startBlock && !endBlock) return;
440
+ if (!startBlock || !endBlock) return true;
441
+ return !_slate.Path.equals(startBlock[1], endBlock[1]);
442
+ } catch (error) {
443
+ return true;
444
+ }
441
445
  };
442
446
  exports.isRangeAcrossBlocks = isRangeAcrossBlocks;
443
447
  const isAncestorEmpty = (editor, node) => {
@@ -26,12 +26,12 @@ const isMenuDisabled = (editor, readonly) => {
26
26
  } = editor;
27
27
  if (!selection) return true;
28
28
  const selectedElements = (0, _core.getSelectedElems)(editor);
29
- const isRangeAcrossBlock = (0, _core.isRangeAcrossBlocks)(editor);
30
29
  // If it's not the top list item, disable callout menu
31
30
  const [node] = (0, _core.getTopLevelBlockNode)(editor) || [];
32
31
  if (node && [_elementType.ORDERED_LIST, _elementType.UNORDERED_LIST].includes(node === null || node === void 0 ? void 0 : node.type)) {
33
32
  if (!(0, _core.isTopLevelListItem)(editor)) return true;
34
33
  }
34
+ const isRangeAcrossBlock = (0, _core.isRangeAcrossBlocks)(editor);
35
35
  // If selected multiple block element contains callout, disable callout menu
36
36
  const isAllSelectedElementsInAllowTypes = selectedElements.length && selectedElements.every(element => {
37
37
  if (element.type === _elementType.CALL_OUT && isRangeAcrossBlock) return false;
@@ -39,6 +39,7 @@ const getFontSize = editor => {
39
39
  return marks[_constants.TEXT_STYLE_MAP.FONT_SIZE];
40
40
  }
41
41
  if (!selection) return _constants.SDOC_FONT_SIZE.DEFAULT;
42
+ if ((0, _core.isRangeAcrossBlocks)(editor)) return _constants.SDOC_FONT_SIZE.DEFAULT;
42
43
  const [match] = _slate.Editor.nodes(editor, {
43
44
  at: _slate.Editor.unhangRange(editor, selection),
44
45
  match: n => {
@@ -95,6 +96,9 @@ const getFont = editor => {
95
96
  return marks[_constants.TEXT_STYLE_MAP.FONT];
96
97
  }
97
98
  if (!selection) return _constants.DEFAULT_FONT;
99
+ if ((0, _core.isRangeAcrossBlocks)(editor, {
100
+ at: selection
101
+ })) return _constants.DEFAULT_FONT;
98
102
  const [match] = _slate.Editor.nodes(editor, {
99
103
  at: _slate.Editor.unhangRange(editor, selection),
100
104
  match: n => !_slate.Editor.isEditor(n) && !_slate.Element.isElement(n) && n['font']
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.unwrapLinkNode = exports.sdocFileIcon = exports.removeTempInput = exports.removeShortCutSymbol = exports.onCopySdocLinkNode = exports.isTriggeredByShortcut = exports.isMenuDisabled = exports.insertTextWhenRemoveFileNameCollector = exports.insertTempInput = exports.insertSdocFileLink = exports.getUrl = exports.getType = exports.getSdocLinkEntry = exports.getNewFileListData = exports.getFileSearchInputEntry = exports.getBeforeText = exports.generateSdocFileNode = void 0;
7
+ exports.unwrapLinkNode = exports.removeTempInput = exports.removeShortCutSymbol = exports.onCopySdocLinkNode = exports.isTriggeredByShortcut = exports.isMenuDisabled = exports.insertTextWhenRemoveFileNameCollector = exports.insertTempInput = exports.insertSdocFileLink = exports.getUrl = exports.getType = exports.getSdocLinkEntry = exports.getSdocFileIcon = exports.getNewFileListData = exports.getFileSearchInputEntry = exports.getBeforeText = exports.generateSdocFileNode = void 0;
8
8
  var _slateReact = require("@seafile/slate-react");
9
9
  var _slate = require("@seafile/slate");
10
10
  var _slugid = _interopRequireDefault(require("slugid"));
@@ -274,11 +274,11 @@ const insertTextWhenRemoveFileNameCollector = (editor, searchInputNode) => {
274
274
  removeTempInput(editor, searchInputNode);
275
275
  };
276
276
  exports.insertTextWhenRemoveFileNameCollector = insertTextWhenRemoveFileNameCollector;
277
- const sdocFileIcon = () => {
277
+ const getSdocFileIcon = () => {
278
278
  const server = _context.default.getSetting('serviceUrl');
279
279
  return `${server}/media/img/file/256/sdoc.png`;
280
280
  };
281
- exports.sdocFileIcon = sdocFileIcon;
281
+ exports.getSdocFileIcon = getSdocFileIcon;
282
282
  const getSdocLinkEntry = function (editor) {
283
283
  let at = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : editor.selection;
284
284
  const aboveNodeEntry = _slate.Editor.above(editor, {
@@ -147,7 +147,7 @@ const SdocFileLink = _ref => {
147
147
  style: style
148
148
  }, element.type !== _elementType.WIKI_LINK && /*#__PURE__*/_react.default.createElement("img", {
149
149
  className: "file-link-img",
150
- src: (0, _helpers.sdocFileIcon)(),
150
+ src: (0, _helpers.getSdocFileIcon)(),
151
151
  alt: ""
152
152
  }), element.type === _elementType.WIKI_LINK && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, icon && /*#__PURE__*/_react.default.createElement("span", null, icon), !icon && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, isDir ? /*#__PURE__*/_react.default.createElement("span", {
153
153
  className: "sf3-font sf3-font-files2"
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.setAlignType = exports.isMenuDisabled = exports.getAlignType = void 0;
7
7
  var _slate = require("@seafile/slate");
8
8
  var _constants = require("../../constants");
9
+ var _core = require("../../core");
9
10
  const isMenuDisabled = (editor, readonly) => {
10
11
  if (readonly) return true;
11
12
  if (!editor.selection) return true;
@@ -33,6 +34,7 @@ const getAlignType = editor => {
33
34
  if (!selection) {
34
35
  return defaultType;
35
36
  }
37
+ if ((0, _core.isRangeAcrossBlocks)(editor)) return defaultType;
36
38
  const [match] = _slate.Editor.nodes(editor, {
37
39
  at: _slate.Editor.unhangRange(editor, selection),
38
40
  match: n => !_slate.Editor.isEditor(n) && _slate.Element.isElement(n) && n['align']
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+
3
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _react = _interopRequireWildcard(require("react"));
9
+ var _reactI18next = require("react-i18next");
10
+ var _reactstrap = require("reactstrap");
11
+ var _helpers = require("../../helpers");
12
+ const AddVideoLinkDialog = _ref => {
13
+ let {
14
+ editor,
15
+ className,
16
+ closeDialog,
17
+ handleSubmit
18
+ } = _ref;
19
+ const {
20
+ t
21
+ } = (0, _reactI18next.useTranslation)('sdoc-editor');
22
+ const [linkErrorMessage, setLinkErrorMessage] = (0, _react.useState)('');
23
+ const [url, setURL] = (0, _react.useState)('');
24
+ const isValidVideoLink = link => {
25
+ const videoRegex = /v\.qq\.com|youtube\.com|v\.youku\.com|bilibili\.com/i;
26
+ return videoRegex.test(link);
27
+ };
28
+ const submit = (0, _react.useCallback)(() => {
29
+ setLinkErrorMessage('');
30
+ if (!url) {
31
+ setLinkErrorMessage(t('The_link_address_is_required'));
32
+ return;
33
+ }
34
+ if (!isValidVideoLink(url)) {
35
+ setLinkErrorMessage(t('The_link_address_is_invalid'));
36
+ return;
37
+ }
38
+ (0, _helpers.insertVideo)(editor, [{
39
+ name: url,
40
+ isEmbeddableLink: true
41
+ }], [url]);
42
+ handleSubmit && handleSubmit();
43
+ closeDialog();
44
+
45
+ // eslint-disable-next-line react-hooks/exhaustive-deps
46
+ }, [editor, url]);
47
+ const onKeyDown = (0, _react.useCallback)(event => {
48
+ if (event.keyCode === 13) {
49
+ event.preventDefault();
50
+ submit();
51
+ return;
52
+ }
53
+ // eslint-disable-next-line react-hooks/exhaustive-deps
54
+ }, [editor, url]);
55
+ const handleUrlChange = (0, _react.useCallback)(event => {
56
+ const videoUrl = event.target.value;
57
+ if (videoUrl === url) return;
58
+ setURL(videoUrl);
59
+ }, [url]);
60
+ return /*#__PURE__*/_react.default.createElement(_reactstrap.Modal, {
61
+ isOpen: true,
62
+ autoFocus: false,
63
+ toggle: closeDialog,
64
+ className: className,
65
+ zIndex: 1071,
66
+ returnFocusAfterClose: false
67
+ }, /*#__PURE__*/_react.default.createElement(_reactstrap.ModalHeader, {
68
+ toggle: closeDialog
69
+ }, t('Insert_link')), /*#__PURE__*/_react.default.createElement(_reactstrap.ModalBody, null, /*#__PURE__*/_react.default.createElement(_react.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
70
+ className: "form-group"
71
+ }, /*#__PURE__*/_react.default.createElement(_reactstrap.Label, {
72
+ for: "addLink"
73
+ }, t('Link_address')), /*#__PURE__*/_react.default.createElement("input", {
74
+ onKeyDown: onKeyDown,
75
+ autoFocus: true,
76
+ type: "url",
77
+ className: "form-control",
78
+ id: "addVideoLink",
79
+ value: url || '',
80
+ onChange: handleUrlChange
81
+ }), linkErrorMessage && /*#__PURE__*/_react.default.createElement(_reactstrap.Alert, {
82
+ color: "danger",
83
+ className: "mt-2"
84
+ }, t(linkErrorMessage))), /*#__PURE__*/_react.default.createElement("div", {
85
+ style: {
86
+ textAlign: 'center',
87
+ fontSize: '12px',
88
+ color: '#787774'
89
+ }
90
+ }, t('Support_Youtube_Tencent_Bilibili_and_more')))), /*#__PURE__*/_react.default.createElement(_reactstrap.ModalFooter, null, /*#__PURE__*/_react.default.createElement(_reactstrap.Button, {
91
+ color: "secondary",
92
+ onClick: closeDialog
93
+ }, t('Cancel')), /*#__PURE__*/_react.default.createElement(_reactstrap.Button, {
94
+ color: "primary",
95
+ disabled: false,
96
+ onClick: submit
97
+ }, t('Add_link'))));
98
+ };
99
+ var _default = exports.default = AddVideoLinkDialog;
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.videoFileIcon = exports.isInsertVideoMenuDisabled = exports.insertVideo = exports.getVideoURL = exports.generateVideoNode = exports.formatFileSize = void 0;
7
+ exports.videoFileIcon = exports.parseVideoLink = exports.isInsertVideoMenuDisabled = exports.insertVideo = exports.getVideoURL = exports.generateVideoNode = exports.formatFileSize = void 0;
8
8
  var _urlJoin = _interopRequireDefault(require("url-join"));
9
9
  var _slate = require("@seafile/slate");
10
10
  var _core = require("../../core");
@@ -43,26 +43,79 @@ const isInsertVideoMenuDisabled = (editor, readonly) => {
43
43
  return false;
44
44
  };
45
45
  exports.isInsertVideoMenuDisabled = isInsertVideoMenuDisabled;
46
- const generateVideoNode = (src, videoFiles) => {
46
+ const generateVideoNode = (src, videoInfo) => {
47
47
  const element = (0, _core.generateEmptyElement)(_constants.VIDEO);
48
- return {
48
+ const {
49
+ name,
50
+ size,
51
+ is_embeddable_link
52
+ } = videoInfo;
53
+ return [{
49
54
  ...element,
50
55
  data: {
51
56
  src,
52
- videoFiles
57
+ name,
58
+ size,
59
+ is_embeddable_link
53
60
  }
54
- };
61
+ }];
55
62
  };
56
63
  exports.generateVideoNode = generateVideoNode;
64
+ const parseVideoLink = url => {
65
+ if (!url) return false;
66
+
67
+ // Youtube url conversion
68
+ if (url.includes('youtube.com')) {
69
+ const videoId = new URL(url).searchParams.get('v');
70
+ const videoUrl = videoId ? `https://www.youtube.com/embed/${videoId}/?rel=0` : false;
71
+ return videoUrl;
72
+ }
73
+
74
+ // Tencent url conversion
75
+ if (url.includes('v.qq.com')) {
76
+ const vidMatch = url.match(/\/([^\/]+)\.html/);
77
+ const videoUrl = vidMatch !== null && vidMatch !== void 0 && vidMatch[1] ? `https://v.qq.com/txp/iframe/player.html?vid=${vidMatch[1]}` : false;
78
+ return videoUrl;
79
+ }
80
+
81
+ // Bilibili url conversion
82
+ if (url.includes('bilibili.com')) {
83
+ const vidMatch = url.match(/\/video\/(BV[0-9A-Za-z]+)/);
84
+ const videoUrl = vidMatch !== null && vidMatch !== void 0 && vidMatch[1] ? `https://player.bilibili.com/player.html?bvid=${vidMatch[1]}` : false;
85
+ return videoUrl;
86
+ }
87
+
88
+ // Youku url conversion
89
+ if (url.includes('v.youku.com')) {
90
+ const vidMatch = url.match(/id_([A-Za-z0-9=]+)\.html/);
91
+ const videoUrl = vidMatch !== null && vidMatch !== void 0 && vidMatch[1] ? `https://player.youku.com/embed/${vidMatch[1]}` : false;
92
+ return videoUrl;
93
+ }
94
+
95
+ // Unsupported url
96
+ return false;
97
+ };
98
+ exports.parseVideoLink = parseVideoLink;
57
99
  const insertVideo = function (editor, videoFiles, srcList, selection) {
58
100
  let position = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : _constants.INSERT_POSITION.CURRENT;
59
101
  if (!srcList) return;
60
102
  if (position !== _constants.INSERT_POSITION.AFTER) {
61
103
  if (isInsertVideoMenuDisabled(editor)) return;
62
104
  }
63
- const videoNodes = srcList.map(src => {
64
- return generateVideoNode(src, videoFiles);
65
- });
105
+ const videoInfo = {
106
+ name: videoFiles[0].name || null,
107
+ size: videoFiles[0].size || null,
108
+ is_embeddable_link: videoFiles[0].isEmbeddableLink || false
109
+ };
110
+ let videoNodes;
111
+ // Return when embedding an invalid youtube, tencent or bilibili video url
112
+ if (videoInfo.is_embeddable_link) {
113
+ const parsedSrc = parseVideoLink(srcList[0]);
114
+ if (!parsedSrc) return;
115
+ videoNodes = generateVideoNode(parsedSrc, videoInfo);
116
+ } else {
117
+ videoNodes = generateVideoNode(srcList[0], videoInfo);
118
+ }
66
119
  const validSelection = selection || editor.selection;
67
120
  let path = _slate.Editor.path(editor, validSelection);
68
121
  if (position === _constants.INSERT_POSITION.AFTER) {
@@ -1,7 +1,7 @@
1
1
  .video-loading-placeholder {
2
2
  background-color: #F2F2F2;
3
3
  width: 100%;
4
- height: 45px;
4
+ height: auto;
5
5
  display: flex;
6
6
  align-items: center;
7
7
  }
@@ -49,14 +49,15 @@
49
49
 
50
50
  .sdoc-video-wrapper .sdoc-video-inner {
51
51
  position: relative;
52
- width: 670px;
52
+ width: 100%;
53
+ aspect-ratio: 16 / 9;
53
54
  display: flex;
54
55
  margin-top: 5px;
55
56
  margin-bottom: 10px;
56
57
  }
57
58
 
58
59
  .sdoc-video-inner .sdoc-video-element{
59
- width: 670px;
60
+ width: 100%;
60
61
  }
61
62
 
62
63
  .sdoc-video-inner .sdoc-video-element:focus-visible {