@seafile/sdoc-editor 1.0.211-test-0.4 → 1.0.212-alph-0.0.1

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/assets/css/sdoc-editor-plugins.css +0 -56
  2. package/dist/basic-sdk/editor/revision-editor.js +1 -0
  3. package/dist/basic-sdk/extension/commons/file-insert-dialog/index.js +1 -1
  4. package/dist/basic-sdk/extension/commons/insert-element-dialog/index.js +21 -0
  5. package/dist/basic-sdk/extension/commons/select-file-dialog/helpers.js +8 -3
  6. package/dist/basic-sdk/extension/commons/select-file-dialog/index.js +48 -8
  7. package/dist/basic-sdk/extension/commons/select-file-dialog/local-files/index.css +1 -0
  8. package/dist/basic-sdk/extension/commons/select-file-dialog/local-files/index.js +6 -2
  9. package/dist/basic-sdk/extension/constants/element-type.js +2 -1
  10. package/dist/basic-sdk/extension/constants/index.js +2 -1
  11. package/dist/basic-sdk/extension/plugins/image/render-elem.js +15 -87
  12. package/dist/basic-sdk/extension/plugins/sdoc-link/helpers.js +3 -3
  13. package/dist/basic-sdk/extension/plugins/sdoc-link/render/render-elem.js +1 -1
  14. package/dist/basic-sdk/extension/plugins/video/dialog/add-video-link-dialog/index.js +99 -0
  15. package/dist/basic-sdk/extension/plugins/video/helpers.js +61 -8
  16. package/dist/basic-sdk/extension/plugins/video/index.css +4 -3
  17. package/dist/basic-sdk/extension/plugins/video/menu/index.js +24 -1
  18. package/dist/basic-sdk/extension/plugins/video/render-elem.js +20 -7
  19. package/dist/basic-sdk/views/revision-diff-viewer.js +1 -0
  20. package/dist/constants/index.js +1 -0
  21. package/dist/pages/simple-editor.js +1 -0
  22. package/package.json +1 -1
  23. package/public/locales/cs/sdoc-editor.json +5 -3
  24. package/public/locales/de/sdoc-editor.json +5 -3
  25. package/public/locales/en/sdoc-editor.json +5 -3
  26. package/public/locales/es/sdoc-editor.json +5 -3
  27. package/public/locales/es_AR/sdoc-editor.json +5 -3
  28. package/public/locales/es_MX/sdoc-editor.json +5 -3
  29. package/public/locales/fr/sdoc-editor.json +5 -3
  30. package/public/locales/it/sdoc-editor.json +5 -3
  31. package/public/locales/ru/sdoc-editor.json +5 -3
  32. package/public/locales/zh_CN/sdoc-editor.json +4 -2
@@ -62,62 +62,6 @@
62
62
  caret-color: transparent;
63
63
  }
64
64
 
65
- .sdoc-editor__article .sdoc-image-wrapper .sdoc-image-placeholder-wrapper {
66
- /* width: 360px; */
67
- width: 100%;
68
- aspect-ratio: 1 / 1;
69
- background-color: #f0f0f0;
70
- border: 1px solid #ccc;
71
- padding: 0 3%;
72
- max-width: 100%;
73
- user-select: all;
74
- pointer-events: all;
75
- }
76
-
77
- .sdoc-editor__article .sdoc-image-wrapper .sdoc-image-tip-content,
78
- .sdoc-editor__article .sdoc-image-wrapper .sdoc-image-title {
79
- user-select: none;
80
- pointer-events: none;
81
- }
82
-
83
- .sdoc-editor__article .sdoc-image-title .sdoc-exclamation-circle {
84
- font-size: 18px;
85
- align-items: center;
86
- justify-content: center;
87
- color: red;
88
- display: flex;
89
- }
90
-
91
- .sdoc-editor__article .sdoc-image-title .sdoc-image-tip-title {
92
- color: red;
93
- font-size: 18px;
94
- user-select: none;
95
- pointer-events: none;
96
- }
97
-
98
- .sdoc-editor__article .sdoc-image-process-container {
99
- width: 40px;
100
- height: 40px;
101
- display: flex;
102
- align-items: center;
103
- }
104
-
105
- .sdoc-editor__article .sdoc-image-process-container .loading-spinner {
106
- border: 5px solid #d8d8d8;
107
- border-top: 5px solid #939393;
108
- border-radius: 50%;
109
- width: 30px;
110
- height: 30px;
111
- animation: spin 1s linear infinite;
112
- user-select: none;
113
- pointer-events: none;
114
- }
115
-
116
- @keyframes spin {
117
- 0% { transform: rotate(0deg); }
118
- 100% { transform: rotate(360deg); }
119
- }
120
-
121
65
  .sdoc-editor__article .sdoc-image-inner {
122
66
  position: relative;
123
67
  display: inline-block;
@@ -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 = {
@@ -20,8 +20,9 @@ var _useScrollContext = require("../../../hooks/use-scroll-context");
20
20
  var _constants2 = require("./constants");
21
21
  var _constants3 = require("../../constants");
22
22
  var _constants4 = require("../../../../constants");
23
+ var _imagePlaceholder = _interopRequireDefault(require("../../../assets/images/image-placeholder.png"));
23
24
  const Image = _ref => {
24
- var _imageRef$current, _imageRef$current2, _imageRef$current3;
25
+ var _imageRef$current, _imageRef$current2;
25
26
  let {
26
27
  element,
27
28
  editor,
@@ -56,7 +57,6 @@ const Image = _ref => {
56
57
  const [isShowImageHoverMenu, setIsShowImageHoverMenu] = (0, _react.useState)(false);
57
58
  const [menuPosition, setMenuPosition] = (0, _react.useState)({});
58
59
  const [caption, setCaption] = (0, _react.useState)((data === null || data === void 0 ? void 0 : data.caption) || '');
59
- const [isLoading, setIsLoading] = (0, _react.useState)(true);
60
60
  const registerEvent = (0, _react.useCallback)(eventList => {
61
61
  eventList.forEach(element => {
62
62
  document.addEventListener(element.eventName, element.event);
@@ -71,17 +71,12 @@ const Image = _ref => {
71
71
  var _resizerRef$current;
72
72
  event.preventDefault();
73
73
  event.stopPropagation();
74
- if (!imageRef.current) return;
75
74
  const changeX = event.clientX - ((_resizerRef$current = resizerRef.current) === null || _resizerRef$current === void 0 ? void 0 : _resizerRef$current.getBoundingClientRect().left) - 5;
76
- let newWidth = isShowImagePlaceholder ? imageRef.current.getBoundingClientRect().width + changeX : imageRef.current.width + changeX;
77
- if (newWidth < 20) return;
78
- if (isShowImagePlaceholder) {
79
- imageRef.current.width.baseVal.value = newWidth;
80
- } else {
81
- imageRef.current.width = newWidth;
82
- }
83
- setMovingWidth(newWidth);
84
- }, [isShowImagePlaceholder]);
75
+ const imageWidth = imageRef.current.width + changeX;
76
+ if (imageWidth < 20) return;
77
+ imageRef.current.width = imageWidth;
78
+ setMovingWidth(imageWidth);
79
+ }, []);
85
80
  const onResizeEnd = (0, _react.useCallback)(event => {
86
81
  event.preventDefault();
87
82
  event.stopPropagation();
@@ -207,7 +202,6 @@ const Image = _ref => {
207
202
  if (data.src.startsWith('data:image/jpeg;base64')) {
208
203
  return (0, _helpers.handleBase64Image)(editor, path, data);
209
204
  }
210
- setIsLoading(false);
211
205
  setIsShowImagePlaceholder(true);
212
206
  // External network images do not reload after failure to load
213
207
  if (!data.src.startsWith('http')) {
@@ -230,22 +224,7 @@ const Image = _ref => {
230
224
  });
231
225
  }
232
226
  }, [data, editor, element]);
233
- (0, _react.useEffect)(() => {
234
- if (imageRef.current) {
235
- imageRef.current.onload = () => setIsLoading(false);
236
- imageRef.current.onerror = onImageLoadError;
237
- }
238
- }, [data, editor]);
239
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
240
- className: "sdoc-image-process-container",
241
- style: {
242
- display: isLoading ? 'inline-block' : 'none'
243
- }
244
- }, /*#__PURE__*/_react.default.createElement("div", {
245
- className: "loading-spinner"
246
- }, /*#__PURE__*/_react.default.createElement("div", {
247
- className: "spinner"
248
- })), children), isShowImagePlaceholder && /*#__PURE__*/_react.default.createElement("span", Object.assign({
227
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, isShowImagePlaceholder && /*#__PURE__*/_react.default.createElement("span", Object.assign({
249
228
  className: (0, _classnames.default)('sdoc-image-wrapper', className)
250
229
  }, attributes, {
251
230
  style: {
@@ -254,64 +233,13 @@ const Image = _ref => {
254
233
  onMouseOver: e => (0, _helpers.selectImageWhenSelectPartial)(e, editor, element, isSelected),
255
234
  contentEditable: "false",
256
235
  suppressContentEditableWarning: true
257
- }), /*#__PURE__*/_react.default.createElement("svg", {
258
- xmlns: "http://www.w3.org/2000/svg",
259
- viewBox: "0 0 360 360",
260
- preserveAspectRatio: "xMinYMin meet",
261
- className: (0, _classnames.default)('sdoc-image-placeholder-wrapper', {
262
- 'image-selected': isSelected
263
- }),
236
+ }), /*#__PURE__*/_react.default.createElement("img", {
264
237
  ref: imageRef,
238
+ src: _imagePlaceholder.default,
265
239
  style: getImageStyle(),
266
- draggable: false
267
- }, /*#__PURE__*/_react.default.createElement("rect", {
268
- width: "100%",
269
- height: "100%",
270
- fill: "#f0f0f0"
271
- }), /*#__PURE__*/_react.default.createElement("g", {
272
- className: "sdoc-image-content-wrapper",
273
- textAnchor: "middle",
274
- dominantBaseline: "middle",
275
- transform: "translate(180, 180)"
276
- }, /*#__PURE__*/_react.default.createElement("g", {
277
- className: "sdoc-image-title",
278
- transform: "translate(0, 0)"
279
- }, /*#__PURE__*/_react.default.createElement("foreignObject", {
280
- x: "-22%",
281
- y: "-16",
282
- width: "20",
283
- height: "28"
284
- }, /*#__PURE__*/_react.default.createElement("div", {
285
- className: "sdocfont sdoc-exclamation-circle"
286
- })), /*#__PURE__*/_react.default.createElement("text", {
287
- className: "sdoc-image-tip-title",
288
- x: "5%",
289
- fontSize: "20",
290
- fill: "red",
291
- fontFamily: "Arial, sans-serif"
292
- }, t('Image_copy_error'))), /*#__PURE__*/_react.default.createElement("text", {
293
- className: "sdoc-image-tip-content",
294
- x: "0",
295
- y: "10%",
296
- fontSize: "12",
297
- textAnchor: "middle",
298
- fill: "black",
299
- fontFamily: "Arial, sans-serif"
300
- }, t('Image_cannot_be_copied_Please_download_the_source_image')), /*#__PURE__*/_react.default.createElement("text", {
301
- className: "sdoc-image-tip-content",
302
- x: "0",
303
- y: "16%",
304
- fontSize: "12",
305
- textAnchor: "middle",
306
- fill: "black",
307
- fontFamily: "Arial, sans-serif"
308
- }, t('And_select_insert_-_image_to_upload')))), isSelected && /*#__PURE__*/_react.default.createElement("span", {
309
- className: "image-resizer",
310
- ref: resizerRef,
311
- onMouseDown: onResizeStart
312
- }), isResizing && /*#__PURE__*/_react.default.createElement("span", {
313
- className: "image-size"
314
- }, /*#__PURE__*/_react.default.createElement("span", null, t('Width'), ':', parseInt(movingWidth || ((_imageRef$current = imageRef.current) === null || _imageRef$current === void 0 ? void 0 : _imageRef$current.clientWidth))), /*#__PURE__*/_react.default.createElement("span", null, "\xA0\xA0"), /*#__PURE__*/_react.default.createElement("span", null, t('Height'), ':', imageRef.current.clientHeight)), children), !isShowImagePlaceholder && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", Object.assign({
240
+ draggable: false,
241
+ alt: ""
242
+ }), children), !isShowImagePlaceholder && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", Object.assign({
315
243
  "data-id": element.id,
316
244
  className: (0, _classnames.default)('sdoc-image-wrapper', className)
317
245
  }, attributes, {
@@ -344,12 +272,12 @@ const Image = _ref => {
344
272
  onMouseDown: onResizeStart
345
273
  }), isResizing && /*#__PURE__*/_react.default.createElement("span", {
346
274
  className: "image-size"
347
- }, /*#__PURE__*/_react.default.createElement("span", null, t('Width'), ':', parseInt(movingWidth || ((_imageRef$current2 = imageRef.current) === null || _imageRef$current2 === void 0 ? void 0 : _imageRef$current2.clientWidth))), /*#__PURE__*/_react.default.createElement("span", null, "\xA0\xA0"), /*#__PURE__*/_react.default.createElement("span", null, t('Height'), ':', imageRef.current.clientHeight))), nodeEntry[0].type === _constants3.IMAGE_BLOCK && show_caption && /*#__PURE__*/_react.default.createElement("input", {
275
+ }, /*#__PURE__*/_react.default.createElement("span", null, t('Width'), ':', parseInt(movingWidth || ((_imageRef$current = imageRef.current) === null || _imageRef$current === void 0 ? void 0 : _imageRef$current.clientWidth))), /*#__PURE__*/_react.default.createElement("span", null, "\xA0\xA0"), /*#__PURE__*/_react.default.createElement("span", null, t('Height'), ':', imageRef.current.clientHeight))), nodeEntry[0].type === _constants3.IMAGE_BLOCK && show_caption && /*#__PURE__*/_react.default.createElement("input", {
348
276
  id: "sdoc-image-caption-input",
349
277
  ref: imageCaptionInputRef,
350
278
  className: "sdoc-image-caption-input-wrapper",
351
279
  style: {
352
- width: (data === null || data === void 0 ? void 0 : data.width) || ((_imageRef$current3 = imageRef.current) === null || _imageRef$current3 === void 0 ? void 0 : _imageRef$current3.clientWidth)
280
+ width: (data === null || data === void 0 ? void 0 : data.width) || ((_imageRef$current2 = imageRef.current) === null || _imageRef$current2 === void 0 ? void 0 : _imageRef$current2.clientWidth)
353
281
  },
354
282
  placeholder: t('Caption'),
355
283
  autoComplete: "off",
@@ -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,7 @@ 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('diff', diff);
34
35
  setDiff(diff);
35
36
  didMountCallback && didMountCallback(diff);
36
37
  setIsLoading(false);
@@ -36,6 +36,7 @@ const EXTERNAL_EVENT = exports.EXTERNAL_EVENT = {
36
36
  PARTICIPANT_REMOVED: 'participant-removed',
37
37
  CREATE_SDOC_FILE: 'create_sdoc_file',
38
38
  CREATE_WIKI_PAGE: 'create_wiki_page',
39
+ ADD_VIDEO_LINK: 'add_video_link',
39
40
  // wiki
40
41
  INSERT_LINK: 'insert_link',
41
42
  // document
@@ -52,6 +52,7 @@ const SimpleEditor = _ref => {
52
52
  // eslint-disable-next-line react-hooks/exhaustive-deps
53
53
  }, []);
54
54
  const setDiffChanges = (0, _react.useCallback)(diff => {
55
+ console.log(32323);
55
56
  setChanges(diff);
56
57
  // eslint-disable-next-line react-hooks/exhaustive-deps
57
58
  }, [isShowChanges]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "1.0.211-test-0.4",
3
+ "version": "1.0.212-alph-0.0.1",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",
@@ -573,7 +573,7 @@
573
573
  "Five_column": "5 columns",
574
574
  "Full_width_mode": "Full width mode",
575
575
  "Video": "Video",
576
- "Upload_local_video": "Upload_local_video",
576
+ "Upload_local_video": "Upload local video",
577
577
  "The_current_version_does_not_support_>5MB_video_file": "The_current_version_does_not_support_>5MB_video_file",
578
578
  "Token_expired_Please_refresh_the_page": "Token expired. Please refresh the page.",
579
579
  "Link_to_page": "Link to page",
@@ -607,6 +607,8 @@
607
607
  "Enter_reply": "Enter reply",
608
608
  "Processing_content_cannot_be_empty": "Processing content cannot be empty",
609
609
  "AI_error_message": "Request error, please try again",
610
- "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
611
- "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
610
+ "Add_video_link": "Add video link",
611
+ "Link_Seafile_video_file": "Link Seafile video file",
612
+ "Select_video_file": "Select video file",
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
612
614
  }
@@ -573,7 +573,7 @@
573
573
  "Five_column": "5 Spalten",
574
574
  "Full_width_mode": "Full width mode",
575
575
  "Video": "Video",
576
- "Upload_local_video": "Upload_local_video",
576
+ "Upload_local_video": "Lokales Video hochladen",
577
577
  "The_current_version_does_not_support_>5MB_video_file": "The_current_version_does_not_support_>5MB_video_file",
578
578
  "Token_expired_Please_refresh_the_page": "Der Token ist abgelaufen. Laden Sie die Seite neu.",
579
579
  "Link_to_page": "Link to page",
@@ -607,6 +607,8 @@
607
607
  "Enter_reply": "Antwort eingeben",
608
608
  "Processing_content_cannot_be_empty": "Processing content cannot be empty",
609
609
  "AI_error_message": "Request error, please try again",
610
- "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
611
- "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
610
+ "Add_video_link": "Videolink hinzufügen",
611
+ "Link_Seafile_video_file": "Link Seafile video file",
612
+ "Select_video_file": "Select video file",
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
612
614
  }
@@ -573,7 +573,7 @@
573
573
  "Five_column": "5 columns",
574
574
  "Full_width_mode": "Full width mode",
575
575
  "Video": "Video",
576
- "Upload_local_video": "Upload_local_video",
576
+ "Upload_local_video": "Upload local video",
577
577
  "The_current_version_does_not_support_>5MB_video_file": "The_current_version_does_not_support_>5MB_video_file",
578
578
  "Token_expired_Please_refresh_the_page": "Token expired. Please refresh the page.",
579
579
  "Link_to_page": "Link to page",
@@ -607,6 +607,8 @@
607
607
  "Enter_reply": "Enter reply",
608
608
  "Processing_content_cannot_be_empty": "Processing content cannot be empty",
609
609
  "AI_error_message": "Request error, please try again",
610
- "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
611
- "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
610
+ "Add_video_link": "Add video link",
611
+ "Link_Seafile_video_file": "Link Seafile video file",
612
+ "Select_video_file": "Select video file",
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
612
614
  }
@@ -573,7 +573,7 @@
573
573
  "Five_column": "5 columns",
574
574
  "Full_width_mode": "Full width mode",
575
575
  "Video": "Video",
576
- "Upload_local_video": "Upload_local_video",
576
+ "Upload_local_video": "Upload local video",
577
577
  "The_current_version_does_not_support_>5MB_video_file": "The_current_version_does_not_support_>5MB_video_file",
578
578
  "Token_expired_Please_refresh_the_page": "Token expired. Please refresh the page.",
579
579
  "Link_to_page": "Link to page",
@@ -607,6 +607,8 @@
607
607
  "Enter_reply": "Enter reply",
608
608
  "Processing_content_cannot_be_empty": "Processing content cannot be empty",
609
609
  "AI_error_message": "Request error, please try again",
610
- "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
611
- "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
610
+ "Add_video_link": "Add video link",
611
+ "Link_Seafile_video_file": "Link Seafile video file",
612
+ "Select_video_file": "Select video file",
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
612
614
  }
@@ -573,7 +573,7 @@
573
573
  "Five_column": "5 columns",
574
574
  "Full_width_mode": "Full width mode",
575
575
  "Video": "Video",
576
- "Upload_local_video": "Upload_local_video",
576
+ "Upload_local_video": "Upload local video",
577
577
  "The_current_version_does_not_support_>5MB_video_file": "The_current_version_does_not_support_>5MB_video_file",
578
578
  "Token_expired_Please_refresh_the_page": "Token expired. Please refresh the page.",
579
579
  "Link_to_page": "Link to page",
@@ -607,6 +607,8 @@
607
607
  "Enter_reply": "Enter reply",
608
608
  "Processing_content_cannot_be_empty": "Processing content cannot be empty",
609
609
  "AI_error_message": "Request error, please try again",
610
- "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
611
- "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
610
+ "Add_video_link": "Add video link",
611
+ "Link_Seafile_video_file": "Link Seafile video file",
612
+ "Select_video_file": "Select video file",
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
612
614
  }
@@ -573,7 +573,7 @@
573
573
  "Five_column": "5 columns",
574
574
  "Full_width_mode": "Full width mode",
575
575
  "Video": "Video",
576
- "Upload_local_video": "Upload_local_video",
576
+ "Upload_local_video": "Upload local video",
577
577
  "The_current_version_does_not_support_>5MB_video_file": "The_current_version_does_not_support_>5MB_video_file",
578
578
  "Token_expired_Please_refresh_the_page": "Token expired. Please refresh the page.",
579
579
  "Link_to_page": "Link to page",
@@ -607,6 +607,8 @@
607
607
  "Enter_reply": "Enter reply",
608
608
  "Processing_content_cannot_be_empty": "Processing content cannot be empty",
609
609
  "AI_error_message": "Request error, please try again",
610
- "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
611
- "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
610
+ "Add_video_link": "Add video link",
611
+ "Link_Seafile_video_file": "Link Seafile video file",
612
+ "Select_video_file": "Select video file",
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
612
614
  }
@@ -573,7 +573,7 @@
573
573
  "Five_column": "5 columns",
574
574
  "Full_width_mode": "Full width mode",
575
575
  "Video": "Vidéo",
576
- "Upload_local_video": "Upload_local_video",
576
+ "Upload_local_video": "Upload local video",
577
577
  "The_current_version_does_not_support_>5MB_video_file": "The_current_version_does_not_support_>5MB_video_file",
578
578
  "Token_expired_Please_refresh_the_page": "Token expired. Please refresh the page.",
579
579
  "Link_to_page": "Link to page",
@@ -607,6 +607,8 @@
607
607
  "Enter_reply": "Enter reply",
608
608
  "Processing_content_cannot_be_empty": "Processing content cannot be empty",
609
609
  "AI_error_message": "Request error, please try again",
610
- "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
611
- "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
610
+ "Add_video_link": "Add video link",
611
+ "Link_Seafile_video_file": "Link Seafile video file",
612
+ "Select_video_file": "Select video file",
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
612
614
  }
@@ -573,7 +573,7 @@
573
573
  "Five_column": "5 columns",
574
574
  "Full_width_mode": "Full width mode",
575
575
  "Video": "Video",
576
- "Upload_local_video": "Upload_local_video",
576
+ "Upload_local_video": "Upload local video",
577
577
  "The_current_version_does_not_support_>5MB_video_file": "The_current_version_does_not_support_>5MB_video_file",
578
578
  "Token_expired_Please_refresh_the_page": "Token expired. Please refresh the page.",
579
579
  "Link_to_page": "Link to page",
@@ -607,6 +607,8 @@
607
607
  "Enter_reply": "Enter reply",
608
608
  "Processing_content_cannot_be_empty": "Processing content cannot be empty",
609
609
  "AI_error_message": "Request error, please try again",
610
- "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
611
- "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
610
+ "Add_video_link": "Add video link",
611
+ "Link_Seafile_video_file": "Link Seafile video file",
612
+ "Select_video_file": "Select video file",
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
612
614
  }
@@ -573,7 +573,7 @@
573
573
  "Five_column": "5 столбцов",
574
574
  "Full_width_mode": "Режим полной ширины",
575
575
  "Video": "Видео",
576
- "Upload_local_video": "Загрузка_локального_видео",
576
+ "Upload_local_video": "Загрузить локального видео",
577
577
  "The_current_version_does_not_support_>5MB_video_file": "Текущая_версия_не_поддерживает_видео_файл_>5_МБ",
578
578
  "Token_expired_Please_refresh_the_page": "Срок действия токена истек. Обновите страницу.",
579
579
  "Link_to_page": "Ссылка на страницу",
@@ -607,6 +607,8 @@
607
607
  "Enter_reply": "Введите ответ",
608
608
  "Processing_content_cannot_be_empty": "Содержимое обработки не может быть пустым",
609
609
  "AI_error_message": "Ошибка запроса, попробуйте еще раз",
610
- "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
611
- "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
610
+ "Add_video_link": "Добавить ссылку на видео",
611
+ "Link_Seafile_video_file": "Ссылка на видео файл Seafile",
612
+ "Select_video_file": "Выбрать видео файл",
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
612
614
  }
@@ -607,6 +607,8 @@
607
607
  "Enter_reply": "输入回复",
608
608
  "Processing_content_cannot_be_empty": "处理内容不能为空",
609
609
  "AI_error_message": "请求错误,请重试",
610
- "Image_cannot_be_copied_Please_download_the_source_image": "此照片不支持复制,请下载原图",
611
- "And_select_insert_-_image_to_upload": "后点击工具栏「插入」- 「照片」上传"
610
+ "Add_video_link": "添加视频链接",
611
+ "Link_Seafile_video_file": "链接Seafile视频文件",
612
+ "Select_video_file": "选择视频文件",
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "支持Youtube,腾讯视频,B站及其他平台"
612
614
  }