@seafile/sdoc-editor 1.0.211 → 1.0.212-alph-0.0.2

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 (31) hide show
  1. package/dist/basic-sdk/editor/revision-editor.js +1 -0
  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 +48 -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/plugins/sdoc-link/helpers.js +3 -3
  11. package/dist/basic-sdk/extension/plugins/sdoc-link/render/render-elem.js +1 -1
  12. package/dist/basic-sdk/extension/plugins/video/dialog/add-video-link-dialog/index.js +99 -0
  13. package/dist/basic-sdk/extension/plugins/video/helpers.js +61 -8
  14. package/dist/basic-sdk/extension/plugins/video/index.css +4 -3
  15. package/dist/basic-sdk/extension/plugins/video/menu/index.js +24 -1
  16. package/dist/basic-sdk/extension/plugins/video/render-elem.js +20 -7
  17. package/dist/basic-sdk/views/revision-diff-viewer.js +2 -0
  18. package/dist/components/doc-operations/revision-operations/changes-count/index.js +3 -0
  19. package/dist/constants/index.js +1 -0
  20. package/dist/pages/simple-editor.js +1 -0
  21. package/package.json +1 -1
  22. package/public/locales/cs/sdoc-editor.json +6 -2
  23. package/public/locales/de/sdoc-editor.json +311 -307
  24. package/public/locales/en/sdoc-editor.json +6 -2
  25. package/public/locales/es/sdoc-editor.json +6 -2
  26. package/public/locales/es_AR/sdoc-editor.json +6 -2
  27. package/public/locales/es_MX/sdoc-editor.json +6 -2
  28. package/public/locales/fr/sdoc-editor.json +6 -2
  29. package/public/locales/it/sdoc-editor.json +6 -2
  30. package/public/locales/ru/sdoc-editor.json +7 -3
  31. package/public/locales/zh_CN/sdoc-editor.json +5 -1
@@ -66,6 +66,7 @@ const RevisionEditor = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
66
66
  // eslint-disable-next-line react-hooks/exhaustive-deps
67
67
  }), [editorRef]);
68
68
  if (isShowChanges) {
69
+ console.log('isShowchange', isShowChanges);
69
70
  return /*#__PURE__*/_react.default.createElement(_views.RevisionDiffViewer, {
70
71
  editor: editor,
71
72
  revisionContent: revisionContent,
@@ -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,31 @@ 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
+ // Get seafile's video download url as src
70
+ const url = `${fileServerRoot}repos/${repoID}/files${fileInfo.path}/?op=download`;
71
+ const encodedUrl = encodeURI(url);
72
+ insertVideo && insertVideo(editor, [{
73
+ name: fileInfo.name
74
+ }], [encodedUrl]);
75
+ break;
76
+ default:
77
+ break;
46
78
  }
47
- }, [insertLinkCallback, dialogType, editor]);
79
+ }, [insertLinkCallback, insertVideoCallback, dialogType, editor]);
48
80
  const onSubmit = (0, _react.useCallback)(() => {
49
81
  if (!currentSelectedFile) return;
50
82
  const {
@@ -53,6 +85,14 @@ const SelectSdocFileDialog = _ref => {
53
85
  let fileInfo = {
54
86
  ...currentSelectedFile
55
87
  };
88
+
89
+ // Insert video element in sdoc
90
+ if (dialogType === _constants.ELEMENT_TYPE.VIDEO) {
91
+ insertFile(fileInfo);
92
+ closeDialog();
93
+ return;
94
+ }
95
+
56
96
  // File has no id
57
97
  if (!file_uuid || file_uuid === '') {
58
98
  _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 = {
@@ -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"
@@ -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 {
@@ -17,6 +17,7 @@ const VideoMenu = _ref => {
17
17
  let {
18
18
  editor,
19
19
  readonly,
20
+ toggle,
20
21
  eventBus
21
22
  } = _ref;
22
23
  const disabled = (0, _helpers.isInsertVideoMenuDisabled)(editor, readonly);
@@ -30,6 +31,22 @@ const VideoMenu = _ref => {
30
31
  editor
31
32
  });
32
33
  }, [editor, eventBus]);
34
+ const addVideoLink = (0, _react.useCallback)(() => {
35
+ eventBus.dispatch(_constants2.INTERNAL_EVENT.INSERT_ELEMENT, {
36
+ type: _constants.ELEMENT_TYPE.VIDEO_LINK,
37
+ editor
38
+ });
39
+ toggle && toggle();
40
+ // eslint-disable-next-line react-hooks/exhaustive-deps
41
+ }, [editor, eventBus]);
42
+ const openSelectVideoFileDialog = (0, _react.useCallback)(() => {
43
+ eventBus.dispatch(_constants2.INTERNAL_EVENT.INSERT_ELEMENT, {
44
+ type: _constants.ELEMENT_TYPE.VIDEO,
45
+ insertVideo: _helpers.insertVideo
46
+ });
47
+ toggle && toggle();
48
+ // eslint-disable-next-line react-hooks/exhaustive-deps
49
+ }, [toggle, eventBus]);
33
50
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_dropdownMenuItem.default, {
34
51
  disabled: disabled,
35
52
  menuConfig: menuConfig,
@@ -48,6 +65,12 @@ const VideoMenu = _ref => {
48
65
  }, /*#__PURE__*/_react.default.createElement("div", {
49
66
  className: "sdoc-dropdown-menu-item",
50
67
  onClick: openLocalVideoDialog
51
- }, t('Upload_local_video')))));
68
+ }, t('Upload_local_video')), /*#__PURE__*/_react.default.createElement("div", {
69
+ className: "sdoc-dropdown-menu-item",
70
+ onClick: addVideoLink
71
+ }, t('Add_video_link')), /*#__PURE__*/_react.default.createElement("div", {
72
+ className: "sdoc-dropdown-menu-item",
73
+ onClick: openSelectVideoFileDialog
74
+ }, t('Link_Seafile_video_file')))));
52
75
  };
53
76
  var _default = exports.default = VideoMenu;
@@ -12,7 +12,7 @@ var _reactI18next = require("react-i18next");
12
12
  var _helpers = require("./helpers");
13
13
  require("./index.css");
14
14
  const Video = _ref => {
15
- var _data$videoFiles$, _data$videoFiles$2, _videoStates$element$;
15
+ var _videoStates$element$;
16
16
  let {
17
17
  element,
18
18
  editor
@@ -24,8 +24,9 @@ const Video = _ref => {
24
24
  const [isLoaded, setIsLoaded] = (0, _react.useState)(false);
25
25
  const [isSelected, setIsSelected] = (0, _react.useState)(false);
26
26
  const [videoStates, setVideoStates] = (0, _react.useState)({});
27
- const videoFileName = data.videoFiles && ((_data$videoFiles$ = data.videoFiles[0]) === null || _data$videoFiles$ === void 0 ? void 0 : _data$videoFiles$.name) || null;
28
- const videoFileSize = data.videoFiles && ((_data$videoFiles$2 = data.videoFiles[0]) === null || _data$videoFiles$2 === void 0 ? void 0 : _data$videoFiles$2.size) || null;
27
+ const videoName = (data === null || data === void 0 ? void 0 : data.name) || (data === null || data === void 0 ? void 0 : data.src);
28
+ const videoSize = data === null || data === void 0 ? void 0 : data.size;
29
+ const isEmbeddableLink = data === null || data === void 0 ? void 0 : data.is_embeddable_link;
29
30
  const handlePlay = () => {
30
31
  setVideoStates(prev => ({
31
32
  ...prev,
@@ -75,9 +76,9 @@ const Video = _ref => {
75
76
  alt: ""
76
77
  }), /*#__PURE__*/_react.default.createElement("div", {
77
78
  className: "video-file-info"
78
- }, /*#__PURE__*/_react.default.createElement("div", null, videoFileName), /*#__PURE__*/_react.default.createElement("div", {
79
+ }, /*#__PURE__*/_react.default.createElement("div", null, videoName), /*#__PURE__*/_react.default.createElement("div", {
79
80
  className: "file-size"
80
- }, /*#__PURE__*/_react.default.createElement("span", null, (0, _helpers.formatFileSize)(videoFileSize), " \u2014 "), /*#__PURE__*/_react.default.createElement("div", {
81
+ }, /*#__PURE__*/_react.default.createElement("span", null, (0, _helpers.formatFileSize)(videoSize), " \u2014 "), /*#__PURE__*/_react.default.createElement("div", {
81
82
  className: "loading-spinner"
82
83
  }, /*#__PURE__*/_react.default.createElement("div", {
83
84
  className: "spinner"
@@ -92,10 +93,10 @@ const Video = _ref => {
92
93
  style: {
93
94
  visibility: isLoaded ? 'visible' : 'hidden'
94
95
  }
95
- }, /*#__PURE__*/_react.default.createElement("video", {
96
+ }, !isEmbeddableLink && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("video", {
96
97
  className: "sdoc-video-element",
97
98
  ref: videoRef,
98
- src: (0, _helpers.getVideoURL)(data, editor),
99
+ src: (0, _helpers.getVideoURL)(data),
99
100
  controls: true,
100
101
  onClick: onClickVideo,
101
102
  draggable: false,
@@ -111,6 +112,18 @@ const Video = _ref => {
111
112
  visibility: isPaused ? 'visible' : 'hidden'
112
113
  },
113
114
  contentEditable: "false"
115
+ })), isEmbeddableLink && /*#__PURE__*/_react.default.createElement("iframe", {
116
+ className: "sdoc-video-element",
117
+ title: data.src,
118
+ allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
119
+ allowFullScreen: true,
120
+ src: (0, _helpers.getVideoURL)(data),
121
+ onLoad: handleVideoLoad,
122
+ style: {
123
+ width: '100%',
124
+ height: '100%',
125
+ border: 'none'
126
+ }
114
127
  }))));
115
128
  };
116
129
  const SdocVideo = (0, _reactI18next.withTranslation)('sdoc-editor')(Video);
@@ -31,6 +31,8 @@ const RevisionDiffViewer = _ref => {
31
31
  let originContent = JSON.parse(originContentString);
32
32
  originContent = (0, _formatSdocContent.formatSdocContent)(originContent);
33
33
  const diff = (0, _diff.getDiff)(revisionContent, originContent);
34
+ console.log(revisionContent, originContent);
35
+ console.log('diff', diff);
34
36
  setDiff(diff);
35
37
  didMountCallback && didMountCallback(diff);
36
38
  setIsLoading(false);
@@ -33,6 +33,7 @@ const ChangesCount = _ref => {
33
33
  }
34
34
  }, 100);
35
35
  }).then(() => {
36
+ console.log('allchange', allChanges);
36
37
  if (allChanges.changes.length !== 0) {
37
38
  const topLevelChanges = (0, _diff.getTopLevelChanges)(allChanges.changes);
38
39
  const changes = (0, _diff.getMergedChanges)(topLevelChanges, allChanges.value);
@@ -75,10 +76,12 @@ const ChangesCount = _ref => {
75
76
  // eslint-disable-next-line react-hooks/exhaustive-deps
76
77
  }, [changes, currentDiffIndex]);
77
78
  if (!Array.isArray(changes) || changes.length === 0) {
79
+ console.log('change', changes);
78
80
  return /*#__PURE__*/_react.default.createElement("div", {
79
81
  className: "sdoc-revision-changes-container d-flex align-items-center pl-2 pr-2 ml-4"
80
82
  }, t('No_changes'));
81
83
  }
84
+ console.log('changes', changes);
82
85
  const changesCount = changes.length;
83
86
  return /*#__PURE__*/_react.default.createElement("div", {
84
87
  className: "sdoc-revision-changes-container d-flex align-items-center ml-4"