@seafile/sdoc-editor 2.0.41 → 2.0.42-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 (35) hide show
  1. package/dist/basic-sdk/editor/sdoc-editor.js +18 -1
  2. package/dist/basic-sdk/extension/commons/insert-element-dialog/index.js +5 -7
  3. package/dist/basic-sdk/extension/plugins/image/helpers.js +48 -12
  4. package/dist/basic-sdk/extension/plugins/image/image-loader/index.css +9 -0
  5. package/dist/basic-sdk/extension/plugins/image/image-loader/index.js +3 -2
  6. package/dist/basic-sdk/extension/plugins/image/plugin.js +2 -3
  7. package/dist/basic-sdk/extension/plugins/image/render-elem.js +16 -3
  8. package/dist/basic-sdk/extension/plugins/image/use-copy-image.js +80 -0
  9. package/dist/basic-sdk/extension/plugins/image/use-upload-image.js +21 -34
  10. package/dist/basic-sdk/extension/plugins/link/hover/index.js +1 -1
  11. package/dist/basic-sdk/extension/plugins/multi-column/render/index.js +2 -3
  12. package/dist/basic-sdk/extension/plugins/search-replace/menu/index.js +2 -2
  13. package/dist/basic-sdk/extension/plugins/search-replace/popover/index.js +1 -1
  14. package/dist/basic-sdk/extension/plugins/seatable-row/dialog/add-seatable-row-dialog/row-card-header.js +1 -1
  15. package/dist/basic-sdk/extension/plugins/seatable-tables/seatable-settings/dtable-search-input/index.js +1 -1
  16. package/dist/basic-sdk/extension/plugins/seatable-tables/seatable-settings/filter-setter/filter-popover-widgets/filter-item.js +1 -1
  17. package/dist/basic-sdk/extension/plugins/table/popover/table-size-popover/index.js +1 -1
  18. package/dist/basic-sdk/extension/plugins/video/render-elem.js +2 -0
  19. package/dist/basic-sdk/extension/toolbar/context-toolbar/index.js +1 -1
  20. package/dist/basic-sdk/extension/toolbar/side-toolbar/index.js +1 -1
  21. package/dist/components/doc-operations/index.js +2 -1
  22. package/dist/components/doc-operations/presentation-operation/index.js +73 -0
  23. package/dist/components/doc-operations/style.css +34 -0
  24. package/dist/components/toast/toaster.js +1 -1
  25. package/dist/utils/image-cache.js +30 -0
  26. package/package.json +1 -1
  27. package/public/locales/en/sdoc-editor.json +2 -1
  28. package/public/locales/zh_CN/sdoc-editor.json +2 -1
  29. package/public/media/sdoc-editor-font/iconfont.css +15 -6
  30. package/public/media/sdoc-editor-font/iconfont.eot +0 -0
  31. package/public/media/sdoc-editor-font/iconfont.svg +4 -0
  32. package/public/media/sdoc-editor-font/iconfont.ttf +0 -0
  33. package/public/media/sdoc-editor-font/iconfont.woff +0 -0
  34. package/public/media/sdoc-editor-font/iconfont.woff2 +0 -0
  35. package/public/media/sdoc-editor-font.css +16 -10
@@ -33,7 +33,8 @@ const SdocEditor = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
33
33
  isReloading,
34
34
  showComment,
35
35
  isShowHeaderToolbar = true,
36
- showOutline = true
36
+ showOutline = true,
37
+ isPresentationMode = false
37
38
  } = _ref;
38
39
  const validEditor = (0, _react.useMemo)(() => {
39
40
  if (propsEditor) return propsEditor;
@@ -189,6 +190,22 @@ const SdocEditor = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
189
190
  showComment: true
190
191
  }))));
191
192
  }
193
+ if (isPresentationMode) {
194
+ return /*#__PURE__*/_react.default.createElement(_layout.EditorContainer, {
195
+ editor: validEditor,
196
+ readonly: isPresentationMode
197
+ }, /*#__PURE__*/_react.default.createElement(_useColorContext.ColorProvider, null, /*#__PURE__*/_react.default.createElement(_layout.EditorContent, {
198
+ docValue: slateValue,
199
+ showOutline: false,
200
+ readonly: isPresentationMode,
201
+ editor: validEditor,
202
+ showComment: false
203
+ }, /*#__PURE__*/_react.default.createElement(_readonlyArticle.default, {
204
+ editor: validEditor,
205
+ slateValue: slateValue,
206
+ showComment: false
207
+ }))));
208
+ }
192
209
  const isShowComment = typeof showComment === 'boolean' ? showComment : true;
193
210
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_layout.EditorContainer, {
194
211
  editor: validEditor
@@ -45,13 +45,11 @@ const InsertElementDialog = _ref => {
45
45
  const uploadLocalImageInputRef = (0, _react.useRef)();
46
46
  const uploadLocalVideoInputRef = (0, _react.useRef)();
47
47
  const onFileChanged = (0, _react.useCallback)(event => {
48
- const files = event.target.files;
49
- _context.default.uploadLocalImage(files).then(fileUrl => {
50
- (0, _helpers.insertImage)(validEditor, fileUrl, validEditor.selection, insertPosition);
51
- if (uploadLocalImageInputRef.current) {
52
- uploadLocalImageInputRef.current.value = '';
53
- }
54
- });
48
+ const imgInfos = (0, _helpers.generateImageInfos)(event.target.files);
49
+ (0, _helpers.insertImage)(validEditor, imgInfos, validEditor.selection, insertPosition);
50
+ if (uploadLocalImageInputRef.current) {
51
+ uploadLocalImageInputRef.current.value = '';
52
+ }
55
53
  // eslint-disable-next-line react-hooks/exhaustive-deps
56
54
  }, [validEditor, uploadLocalImageInputRef, insertPosition, slateNode]);
57
55
  const handleDisplayAlert = (0, _react.useCallback)(() => {
@@ -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.updateImage = exports.selectImageWhenSelectPartial = exports.resetCursor = exports.removeImageBlockNode = exports.queryCopyMoveProgressView = exports.isInsertImageMenuDisabled = exports.isImageUrlIsFromCopy = exports.insertImageFiles = exports.insertImage = exports.hasSdocImages = exports.handleBase64Image = exports.getSingleImageFromFragment = exports.getImageURL = exports.getImageData = exports.generateImageNode = void 0;
7
+ exports.updateImage = exports.selectImageWhenSelectPartial = exports.resetCursor = exports.removeImageBlockNode = exports.queryCopyMoveProgressView = exports.isInsertImageMenuDisabled = exports.isImageUrlIsFromUpload = exports.isImageUrlIsFromCopy = exports.insertImageFiles = exports.insertImage = exports.hasSdocImages = exports.handleBase64Image = exports.getSingleImageFromFragment = exports.getImageURL = exports.getImageData = exports.generateImageNode = exports.generateImageInfos = void 0;
8
8
  var _urlJoin = _interopRequireDefault(require("url-join"));
9
9
  var _slate = require("@seafile/slate");
10
10
  var _slateReact = require("@seafile/slate-react");
@@ -17,6 +17,7 @@ var _helpers = require("../seatable-column/helpers");
17
17
  var _constants = require("../../../constants");
18
18
  var _constants2 = require("../../constants");
19
19
  var _base64ToUnit8array = _interopRequireDefault(require("../../../../utils/base64-to-unit8array"));
20
+ var _imageCache = _interopRequireDefault(require("../../../../utils/image-cache"));
20
21
  const isInsertImageMenuDisabled = (editor, readonly) => {
21
22
  if (readonly) return true;
22
23
  const {
@@ -46,28 +47,36 @@ const isInsertImageMenuDisabled = (editor, readonly) => {
46
47
  return false;
47
48
  };
48
49
  exports.isInsertImageMenuDisabled = isInsertImageMenuDisabled;
49
- const generateImageNode = src => {
50
+ const generateImageNode = (src, file_uuid) => {
50
51
  const element = (0, _core.generateEmptyElement)(_constants2.IMAGE);
52
+ let data = {
53
+ src
54
+ };
55
+ if (file_uuid) {
56
+ data.file_uuid = file_uuid;
57
+ }
51
58
  return {
52
59
  ...element,
53
- data: {
54
- src
55
- }
60
+ data
56
61
  };
57
62
  };
58
63
  exports.generateImageNode = generateImageNode;
59
- const insertImage = function (editor, srcList, selection) {
64
+ const insertImage = function (editor, imgInfos, selection) {
60
65
  let position = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : _constants2.INSERT_POSITION.CURRENT;
61
- if (!srcList) return;
66
+ if (!imgInfos) return;
62
67
  if (position !== _constants2.INSERT_POSITION.AFTER) {
63
68
  if (isInsertImageMenuDisabled(editor)) return;
64
69
  }
65
- const imageNodes = srcList.map(src => {
70
+ const imageNodes = imgInfos.map(_ref => {
71
+ let {
72
+ src,
73
+ file_uuid
74
+ } = _ref;
66
75
  const isCommentEditor = editor.editorType === _constants.COMMENT_EDITOR;
67
76
  const imgSrc = isCommentEditor ? getImageURL({
68
77
  src
69
78
  }) : src;
70
- return generateImageNode(imgSrc);
79
+ return generateImageNode(imgSrc, file_uuid);
71
80
  });
72
81
  const validSelection = selection || editor.selection;
73
82
  let path = _slate.Editor.path(editor, validSelection);
@@ -153,6 +162,11 @@ const getImageURL = (data, editor) => {
153
162
  return imgUrl;
154
163
  }
155
164
  }
165
+
166
+ // upload image | drag drop image | cut image
167
+ if (isImageUrlIsFromUpload(url)) return url;
168
+
169
+ // copy from others doc
156
170
  if (isImageUrlIsFromCopy(url)) return url;
157
171
  const serviceUrl = _context.default.getSetting('serviceUrl');
158
172
  const assetsUrl = _context.default.getSetting('assetsUrl');
@@ -223,9 +237,8 @@ const getSingleImageFromFragment = data => {
223
237
  };
224
238
  exports.getSingleImageFromFragment = getSingleImageFromFragment;
225
239
  const insertImageFiles = (files, editor, targetPath) => {
226
- _context.default.uploadLocalImage(files).then(fileUrl => {
227
- insertImage(editor, fileUrl, targetPath, _constants2.INSERT_POSITION.AFTER);
228
- });
240
+ const imgInfos = generateImageInfos(files);
241
+ insertImage(editor, imgInfos, targetPath, _constants2.INSERT_POSITION.AFTER);
229
242
  };
230
243
  exports.insertImageFiles = insertImageFiles;
231
244
  const selectImageWhenSelectPartial = (event, editor, imageNode, isImageSelected) => {
@@ -284,6 +297,29 @@ const isImageUrlIsFromCopy = url => {
284
297
  return false;
285
298
  };
286
299
  exports.isImageUrlIsFromCopy = isImageUrlIsFromCopy;
300
+ const isImageUrlIsFromUpload = url => {
301
+ if (url && url.startsWith('blob:http')) return true;
302
+ return false;
303
+ };
304
+ exports.isImageUrlIsFromUpload = isImageUrlIsFromUpload;
305
+ const generateImageInfos = files => {
306
+ const newFiles = Array.from(files);
307
+ const imgInfos = newFiles.filter(item => {
308
+ if (item && !item.type.startsWith('image/')) return false;
309
+ if (item && item.type === 'image/svg+xml') return false;
310
+ return true;
311
+ }).map(file => {
312
+ const url = window.URL.createObjectURL(file);
313
+ const file_uuid = _slugid.default.nice();
314
+ _imageCache.default.saveImage(file_uuid, file);
315
+ return {
316
+ src: url,
317
+ file_uuid: file_uuid
318
+ };
319
+ });
320
+ return imgInfos;
321
+ };
322
+ exports.generateImageInfos = generateImageInfos;
287
323
  const removeImageBlockNode = (editor, path) => {
288
324
  _slate.Transforms.removeNodes(editor, {
289
325
  at: path
@@ -37,4 +37,13 @@
37
37
 
38
38
  .sdoc-image-process-container .copyright {
39
39
  margin-top: 4px;
40
+ color: #fff;
41
+ }
42
+
43
+ .sdoc-image-content.upload-error>span {
44
+ min-height: 300px;
45
+ min-width: 400px;
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: center;
40
49
  }
@@ -9,7 +9,8 @@ var _react = _interopRequireDefault(require("react"));
9
9
  require("./index.css");
10
10
  function ImageLoader(_ref) {
11
11
  let {
12
- copyright
12
+ copyright,
13
+ isError
13
14
  } = _ref;
14
15
  return /*#__PURE__*/_react.default.createElement("div", {
15
16
  className: "sdoc-image-process-container"
@@ -18,6 +19,6 @@ function ImageLoader(_ref) {
18
19
  }, /*#__PURE__*/_react.default.createElement("div", {
19
20
  className: "spinner"
20
21
  })), copyright && /*#__PURE__*/_react.default.createElement("div", {
21
- className: "copyright"
22
+ className: `copyright ${isError && 'error'}`
22
23
  }, copyright));
23
24
  }
@@ -75,9 +75,8 @@ const withImage = editor => {
75
75
  }
76
76
  }
77
77
  if (data.types && data.types.includes('Files') && data.files[0].type.includes(_constants.IMAGE)) {
78
- _context.default.uploadLocalImage(data.files).then(fileUrl => {
79
- (0, _helpers.insertImage)(newEditor, fileUrl, editor.selection, _constants.INSERT_POSITION.CURRENT);
80
- });
78
+ const imgInfos = (0, _helpers.generateImageInfos)(data.files);
79
+ (0, _helpers.insertImage)(newEditor, imgInfos, editor.selection, _constants.INSERT_POSITION.CURRENT);
81
80
  return;
82
81
  }
83
82
  insertData(data);
@@ -22,8 +22,9 @@ var _constants3 = require("../../constants");
22
22
  var _constants4 = require("../../../../constants");
23
23
  var _imagePlaceholder = _interopRequireDefault(require("../../../assets/images/image-placeholder.png"));
24
24
  var _copyImageErrorSvg = _interopRequireDefault(require("../../../../components/copy-image-error-svg"));
25
- var _useUploadImage = _interopRequireDefault(require("./use-upload-image"));
26
25
  var _imageLoader = _interopRequireDefault(require("./image-loader"));
26
+ var _useCopyImage = _interopRequireDefault(require("./use-copy-image"));
27
+ var _useUploadImage = _interopRequireDefault(require("./use-upload-image"));
27
28
  const Image = _ref => {
28
29
  var _imageRef$current, _imageRef$current2;
29
30
  let {
@@ -64,6 +65,13 @@ const Image = _ref => {
64
65
  isCopyImageLoading,
65
66
  isCopyImageError,
66
67
  setCopyImageLoading
68
+ } = (0, _useCopyImage.default)({
69
+ editor,
70
+ element
71
+ });
72
+ const {
73
+ isUploadLoading,
74
+ isUploadError
67
75
  } = (0, _useUploadImage.default)({
68
76
  editor,
69
77
  element
@@ -283,7 +291,9 @@ const Image = _ref => {
283
291
  }), /*#__PURE__*/_react.default.createElement("span", {
284
292
  className: "sdoc-image-inner"
285
293
  }, /*#__PURE__*/_react.default.createElement("span", {
286
- className: "sdoc-image-content"
294
+ className: (0, _classnames.default)('sdoc-image-content', {
295
+ 'upload-error': isUploadError
296
+ })
287
297
  }, /*#__PURE__*/_react.default.createElement("span", {
288
298
  style: imageStyle
289
299
  }, /*#__PURE__*/_react.default.createElement("img", {
@@ -298,8 +308,11 @@ const Image = _ref => {
298
308
  onLoad: onImageLoaded,
299
309
  onError: onImageLoadError,
300
310
  alt: ""
301
- }), isCopyImageLoading && /*#__PURE__*/_react.default.createElement(_imageLoader.default, {
311
+ }), (isCopyImageLoading || isUploadLoading) && /*#__PURE__*/_react.default.createElement(_imageLoader.default, {
302
312
  copyright: t('Image_is_uploading')
313
+ }), isUploadError && /*#__PURE__*/_react.default.createElement(_imageLoader.default, {
314
+ copyright: t('Image_is_upload_error'),
315
+ isError: true
303
316
  }), isSelected && /*#__PURE__*/_react.default.createElement("span", {
304
317
  className: "image-resizer",
305
318
  ref: resizerRef,
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _react = require("react");
9
+ var _slate = require("@seafile/slate");
10
+ var _slateReact = require("@seafile/slate-react");
11
+ var _context = _interopRequireDefault(require("../../../../context"));
12
+ var _helpers = require("./helpers");
13
+ const updateImageNode = async function (editor, element, newUrl) {
14
+ let isError = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
15
+ const nodePath = _slateReact.ReactEditor.findPath(editor, element);
16
+ const newData = {
17
+ ...element.data,
18
+ src: newUrl,
19
+ is_copy_error: isError
20
+ };
21
+ _slate.Transforms.setNodes(editor, {
22
+ data: newData
23
+ }, {
24
+ at: nodePath
25
+ });
26
+ };
27
+ const useCopyImage = _ref => {
28
+ let {
29
+ editor,
30
+ element
31
+ } = _ref;
32
+ const {
33
+ data
34
+ } = element;
35
+ const {
36
+ is_copy_error = false
37
+ } = data;
38
+ const [isLoading, setIsLoading] = (0, _react.useState)();
39
+ const [isCopyError, setIsCopyError] = (0, _react.useState)(is_copy_error);
40
+ (0, _react.useEffect)(() => {
41
+ const {
42
+ src: url
43
+ } = data;
44
+ if (isCopyError) return;
45
+ if (!(0, _helpers.isImageUrlIsFromCopy)(url)) return;
46
+ const downloadAndUploadImages = async url => {
47
+ try {
48
+ const response = await fetch(url);
49
+ if (response.ok) {
50
+ const blob = await response.blob();
51
+ const file = new File([blob], 'downloaded_image.png', {
52
+ type: blob.type
53
+ });
54
+ const imageUrl = await _context.default.uploadLocalImage([file]);
55
+ if (imageUrl && imageUrl[0]) {
56
+ updateImageNode(editor, element, imageUrl[0]);
57
+ }
58
+ } else {
59
+ throw new Error(`HTTP error status: ${response.status}`);
60
+ }
61
+ } catch (error) {
62
+ console.error(error);
63
+ updateImageNode(editor, element, url, true);
64
+ setIsCopyError(true);
65
+ } finally {
66
+ setTimeout(() => {
67
+ setIsLoading(false);
68
+ }, 500);
69
+ }
70
+ };
71
+ downloadAndUploadImages(url);
72
+ // eslint-disable-next-line react-hooks/exhaustive-deps
73
+ }, []);
74
+ return {
75
+ isCopyImageLoading: isLoading,
76
+ setCopyImageLoading: setIsLoading,
77
+ isCopyImageError: isCopyError
78
+ };
79
+ };
80
+ var _default = exports.default = useCopyImage;
@@ -10,13 +10,11 @@ var _slate = require("@seafile/slate");
10
10
  var _slateReact = require("@seafile/slate-react");
11
11
  var _context = _interopRequireDefault(require("../../../../context"));
12
12
  var _helpers = require("./helpers");
13
- const updateImageNode = async function (editor, element, newUrl) {
14
- let isError = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
13
+ var _imageCache = _interopRequireDefault(require("../../../../utils/image-cache"));
14
+ const updateImageNode = async (editor, element, newUrl) => {
15
15
  const nodePath = _slateReact.ReactEditor.findPath(editor, element);
16
16
  const newData = {
17
- ...element.data,
18
- src: newUrl,
19
- is_copy_error: isError
17
+ src: newUrl
20
18
  };
21
19
  _slate.Transforms.setNodes(editor, {
22
20
  data: newData
@@ -24,7 +22,7 @@ const updateImageNode = async function (editor, element, newUrl) {
24
22
  at: nodePath
25
23
  });
26
24
  };
27
- const useImageUpload = _ref => {
25
+ const useUploadImage = _ref => {
28
26
  let {
29
27
  editor,
30
28
  element
@@ -32,49 +30,38 @@ const useImageUpload = _ref => {
32
30
  const {
33
31
  data
34
32
  } = element;
35
- const {
36
- is_copy_error = false
37
- } = data;
38
33
  const [isLoading, setIsLoading] = (0, _react.useState)();
39
- const [isCopyError, setIsCopyError] = (0, _react.useState)(is_copy_error);
34
+ const [isUploadError, setIsUploadError] = (0, _react.useState)(false);
40
35
  (0, _react.useEffect)(() => {
41
36
  const {
42
- src: url
37
+ src: url,
38
+ file_uuid
43
39
  } = data;
44
- if (isCopyError) return;
45
- if (!(0, _helpers.isImageUrlIsFromCopy)(url)) return;
46
- const downloadAndUploadImages = async url => {
40
+ if (!(0, _helpers.isImageUrlIsFromUpload)(url)) return;
41
+ setIsLoading(true);
42
+ const uploadCurrentImage = async () => {
47
43
  try {
48
- const response = await fetch(url);
49
- if (response.ok) {
50
- const blob = await response.blob();
51
- const file = new File([blob], 'downloaded_image.png', {
52
- type: blob.type
53
- });
54
- const imageUrl = await _context.default.uploadLocalImage([file]);
55
- if (imageUrl && imageUrl[0]) {
56
- updateImageNode(editor, element, imageUrl[0]);
57
- }
58
- } else {
59
- throw new Error(`HTTP error status: ${response.status}`);
44
+ const fileItem = _imageCache.default.getImage(file_uuid);
45
+ const imageUrl = await _context.default.uploadLocalImage([fileItem]);
46
+ if (imageUrl && imageUrl[0]) {
47
+ updateImageNode(editor, element, imageUrl[0]);
60
48
  }
61
49
  } catch (error) {
62
- console.error(error);
63
- updateImageNode(editor, element, url, true);
64
- setIsCopyError(true);
50
+ console.error(error.message);
51
+ setIsUploadError(true);
65
52
  } finally {
53
+ _imageCache.default.deleteImage(file_uuid);
66
54
  setTimeout(() => {
67
55
  setIsLoading(false);
68
56
  }, 500);
69
57
  }
70
58
  };
71
- downloadAndUploadImages(url);
59
+ uploadCurrentImage(url);
72
60
  // eslint-disable-next-line react-hooks/exhaustive-deps
73
61
  }, []);
74
62
  return {
75
- isCopyImageLoading: isLoading,
76
- setCopyImageLoading: setIsLoading,
77
- isCopyImageError: isCopyError
63
+ isUploadLoading: isLoading,
64
+ isUploadError: isUploadError
78
65
  };
79
66
  };
80
- var _default = exports.default = useImageUpload;
67
+ var _default = exports.default = useUploadImage;
@@ -32,7 +32,7 @@ const LinkHover = _ref => {
32
32
  location.href = element.href;
33
33
  }
34
34
  }, [element.href]);
35
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/(0, _reactDom.createPortal)( /*#__PURE__*/_react.default.createElement("div", {
35
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/(0, _reactDom.createPortal)(/*#__PURE__*/_react.default.createElement("div", {
36
36
  id: "link-op-menu",
37
37
  className: "link-op-menu",
38
38
  style: menuPosition
@@ -27,6 +27,7 @@ const MultiColumn = _ref => {
27
27
  } : {});
28
28
  const multiColumnContainerClassName = (0, _classnames.default)('sdoc-multicolumn-container', className);
29
29
  const [pageWidth, setPageWidth] = (0, _react.useState)((0, _helper.getCurrentPageWidth)(editor));
30
+ const readOnly = (0, _slateReact.useReadOnly)();
30
31
  const handleResizeColumn = newColumn => {
31
32
  (0, _helper.updateColumnWidth)(editor, element, newColumn);
32
33
  };
@@ -79,14 +80,12 @@ const MultiColumn = _ref => {
79
80
  style: style,
80
81
  ref: multiColumn,
81
82
  "data-id": element.id
82
- }, children, /*#__PURE__*/_react.default.createElement(_resizeHandlers.default, {
83
+ }, children, !readOnly && /*#__PURE__*/_react.default.createElement(_resizeHandlers.default, {
83
84
  element: element,
84
85
  handleResizeColumn: handleResizeColumn
85
86
  })));
86
87
  };
87
88
  function renderMultiColumn(props) {
88
- // When read only
89
-
90
89
  return /*#__PURE__*/_react.default.createElement(MultiColumn, props);
91
90
  }
92
91
  var _default = exports.default = renderMultiColumn;
@@ -54,7 +54,7 @@ const SearchReplaceMenu = _ref => {
54
54
  const canvasList = [];
55
55
  for (let index = 0; index < generateCount; index++) {
56
56
  const top = index * 5000;
57
- canvasList.push( /*#__PURE__*/_react.default.createElement("canvas", {
57
+ canvasList.push(/*#__PURE__*/_react.default.createElement("canvas", {
58
58
  key: 'sdoc-find-search-' + index,
59
59
  id: `sdoc-find-search-${index}`,
60
60
  className: "sdoc-find-search-highlight-canvas",
@@ -79,7 +79,7 @@ const SearchReplaceMenu = _ref => {
79
79
  readonly: readonly,
80
80
  isOpen: isOpenPopover,
81
81
  closePopover: onMouseDown
82
- }), isOpenPopover && /*#__PURE__*/(0, _reactDom.createPortal)( /*#__PURE__*/_react.default.createElement("div", {
82
+ }), isOpenPopover && /*#__PURE__*/(0, _reactDom.createPortal)(/*#__PURE__*/_react.default.createElement("div", {
83
83
  style: {
84
84
  height: articleContainerSize.clientHeight
85
85
  },
@@ -168,7 +168,7 @@ const SearchReplacePopover = _ref => {
168
168
  if ((0, _isHotkey.default)('enter', e)) handleNext();
169
169
  if ((0, _isHotkey.default)('enter+shift', e)) handleLast();
170
170
  };
171
- return /*#__PURE__*/(0, _reactDom.createPortal)( /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
171
+ return /*#__PURE__*/(0, _reactDom.createPortal)(/*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
172
172
  className: "sdoc-search-replace-popover-container",
173
173
  onMouseDown: handleStartMove,
174
174
  onMouseMove: handleMouseMove,
@@ -78,7 +78,7 @@ class RowCardHeader extends _react.default.Component {
78
78
  // Start from the second column without name
79
79
  for (let i = 1; i < renderedColumns.length; i++) {
80
80
  const renderedColumn = renderedColumns[i];
81
- cardHeaderCells.push( /*#__PURE__*/_react.default.createElement(_rowCardHeaderCell.default, {
81
+ cardHeaderCells.push(/*#__PURE__*/_react.default.createElement(_rowCardHeaderCell.default, {
82
82
  key: renderedColumn.key,
83
83
  column: renderedColumn,
84
84
  rowCardType: rowCardType,
@@ -70,7 +70,7 @@ class DtableSearchInput extends _react.Component {
70
70
  const {
71
71
  ClearIndicator
72
72
  } = components;
73
- if ( /*#__PURE__*/_react.default.isValidElement(ClearIndicator)) {
73
+ if (/*#__PURE__*/_react.default.isValidElement(ClearIndicator)) {
74
74
  return /*#__PURE__*/_react.default.cloneElement(ClearIndicator, {
75
75
  clearValue: this.clearSearch
76
76
  });
@@ -310,7 +310,7 @@ class FilterItem extends _react.default.Component {
310
310
  background: inOption.color,
311
311
  color: inOption.textColor || null
312
312
  };
313
- labelArray.push( /*#__PURE__*/_react.default.createElement("span", {
313
+ labelArray.push(/*#__PURE__*/_react.default.createElement("span", {
314
314
  className: className,
315
315
  style: optionStyle,
316
316
  key: 'option_' + item,
@@ -205,7 +205,7 @@ const TableSizePopover = _ref => {
205
205
  });
206
206
  children.push(child);
207
207
  }
208
- tableSize.push( /*#__PURE__*/_react.default.createElement("div", {
208
+ tableSize.push(/*#__PURE__*/_react.default.createElement("div", {
209
209
  key: `sdoc-table-size-row-${i}`,
210
210
  className: "sdoc-table-size-row d-flex"
211
211
  }, children));
@@ -27,6 +27,7 @@ const Video = _ref => {
27
27
  const videoName = (data === null || data === void 0 ? void 0 : data.name) || (data === null || data === void 0 ? void 0 : data.src);
28
28
  const videoSize = data === null || data === void 0 ? void 0 : data.size;
29
29
  const isEmbeddableLink = data === null || data === void 0 ? void 0 : data.is_embeddable_link;
30
+ const readonly = (0, _slateReact.useReadOnly)();
30
31
  const handlePlay = () => {
31
32
  setVideoStates(prev => ({
32
33
  ...prev,
@@ -98,6 +99,7 @@ const Video = _ref => {
98
99
  ref: videoRef,
99
100
  src: (0, _helpers.getVideoURL)(data),
100
101
  controls: true,
102
+ controlsList: readonly && 'nofullscreen',
101
103
  onClick: onClickVideo,
102
104
  draggable: false,
103
105
  onPlay: handlePlay,
@@ -62,7 +62,7 @@ const ContextToolbar = () => {
62
62
  el.removeAttribute('style');
63
63
  }
64
64
  }, []);
65
- return /*#__PURE__*/(0, _reactDom.createPortal)( /*#__PURE__*/_react.default.createElement("div", {
65
+ return /*#__PURE__*/(0, _reactDom.createPortal)(/*#__PURE__*/_react.default.createElement("div", {
66
66
  ref: ref,
67
67
  className: "sdoc-context-toolbar",
68
68
  onMouseDown: onMouseDown,
@@ -274,7 +274,7 @@ const SideToolbar = () => {
274
274
  targetElement = event.currentTarget;
275
275
  targetElement.classList.remove('sdoc-draging');
276
276
  const dragTypes = event.dataTransfer.types;
277
- if (!dragTypes.includes(_event.DRAG_SDOC_EDITOR_ELEMENT)) return;
277
+ if (!dragTypes.includes(_event.DRAG_SDOC_EDITOR_ELEMENT) && dragTypes[0] !== 'Files') return;
278
278
 
279
279
  // Prevent dragging table data to the editor
280
280
  if (dragTypes.includes(_constants2.TABLE_DRAG_KEY)) return;
@@ -14,6 +14,7 @@ var _moreOperations = _interopRequireDefault(require("./more-operations"));
14
14
  var _shareOperation = _interopRequireDefault(require("./share-operation"));
15
15
  var _pluginsOperations = _interopRequireDefault(require("./plugins-operations"));
16
16
  var _utils = require("../../utils");
17
+ var _presentationOperation = _interopRequireDefault(require("./presentation-operation"));
17
18
  require("./style.css");
18
19
  const DocOperations = _ref => {
19
20
  let {
@@ -43,6 +44,6 @@ const DocOperations = _ref => {
43
44
  handleViewChangesToggle: handleViewChangesToggle,
44
45
  handleRevisionMerged: handleRevisionMerged,
45
46
  handleRevisionPublished: handleRevisionPublished
46
- }), !isSdocRevision && /*#__PURE__*/_react.default.createElement(_pluginsOperations.default, null), !isSdocRevision && /*#__PURE__*/_react.default.createElement(_shareOperation.default, null), !isPublished && /*#__PURE__*/_react.default.createElement(_collaboratorsOperation.default, null), !isSdocRevision && /*#__PURE__*/_react.default.createElement(_moreOperations.default, null));
47
+ }), !isSdocRevision && /*#__PURE__*/_react.default.createElement(_presentationOperation.default, null), !isSdocRevision && /*#__PURE__*/_react.default.createElement(_pluginsOperations.default, null), !isSdocRevision && /*#__PURE__*/_react.default.createElement(_shareOperation.default, null), !isPublished && /*#__PURE__*/_react.default.createElement(_collaboratorsOperation.default, null), !isSdocRevision && /*#__PURE__*/_react.default.createElement(_moreOperations.default, null));
47
48
  };
48
49
  var _default = exports.default = (0, _reactI18next.withTranslation)('sdoc-editor')(DocOperations);
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+ var _react = _interopRequireWildcard(require("react"));
10
+ var _sdocEditor = _interopRequireDefault(require("../../../basic-sdk/editor/sdoc-editor"));
11
+ var _reactDom = _interopRequireDefault(require("react-dom"));
12
+ var _hooks = require("../../../hooks");
13
+ var _isHotkey = _interopRequireDefault(require("is-hotkey"));
14
+ const PresentationOperation = () => {
15
+ const {
16
+ document: sdocDocument
17
+ } = (0, _hooks.useDocument)();
18
+ const [showFullscreen, setShowFullscreen] = (0, _react.useState)(false);
19
+ const fullscreenRef = (0, _react.useRef)(null);
20
+ const onPresentationToggle = (0, _react.useCallback)(() => {
21
+ setShowFullscreen(true);
22
+ }, []);
23
+ (0, _react.useEffect)(() => {
24
+ const handleExit = e => {
25
+ if ((0, _isHotkey.default)('esc', e)) {
26
+ if (document.fullscreenElement) {
27
+ document.exitFullscreen();
28
+ }
29
+ }
30
+ };
31
+ const onFullscreenChange = () => {
32
+ if (!document.fullscreenElement) {
33
+ setShowFullscreen(false);
34
+ }
35
+ };
36
+ window.addEventListener('keydown', handleExit);
37
+ document.addEventListener('fullscreenchange', onFullscreenChange);
38
+ return () => {
39
+ window.removeEventListener('keydown', handleExit);
40
+ document.removeEventListener('fullscreenchange', onFullscreenChange);
41
+ };
42
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
+ }, []);
44
+ const FullscreenOverlay = () => {
45
+ _react.default.useEffect(() => {
46
+ const node = fullscreenRef.current;
47
+ if (showFullscreen && node && node.requestFullscreen) {
48
+ node.requestFullscreen().then(() => setShowFullscreen(true)).catch(err => {
49
+ console.error('Failed to enter fullscreen:', err);
50
+ });
51
+ }
52
+ }, []);
53
+ return /*#__PURE__*/_reactDom.default.createPortal(/*#__PURE__*/_react.default.createElement("div", {
54
+ className: "sdoc-presentation-wrapper",
55
+ ref: fullscreenRef
56
+ }, /*#__PURE__*/_react.default.createElement("div", {
57
+ style: {
58
+ flex: 1,
59
+ overflow: 'auto'
60
+ }
61
+ }, /*#__PURE__*/_react.default.createElement(_sdocEditor.default, {
62
+ document: sdocDocument,
63
+ isPresentationMode: true
64
+ }))), window.document.body);
65
+ };
66
+ return /*#__PURE__*/_react.default.createElement("span", {
67
+ className: "op-item",
68
+ onClick: onPresentationToggle
69
+ }, /*#__PURE__*/_react.default.createElement("i", {
70
+ className: "sdocfont sdoc-presentation"
71
+ }), showFullscreen && /*#__PURE__*/_react.default.createElement(FullscreenOverlay, null));
72
+ };
73
+ var _default = exports.default = PresentationOperation;
@@ -34,6 +34,40 @@
34
34
  width: 300px;
35
35
  }
36
36
 
37
+ .sdoc-presentation-wrapper {
38
+ position: fixed;
39
+ top: 0;
40
+ left: 0;
41
+ width: 100vw;
42
+ height: 100vh;
43
+ background-color: #fff;
44
+ z-Index: 1000;
45
+ display: flex;
46
+ flex-direction: column;
47
+ }
48
+
49
+ .sdoc-presentation-wrapper .sdoc-content-wrapper {
50
+ height: 100vh !important;
51
+ }
52
+
53
+ .sdoc-presentation-wrapper .sdoc-article-container {
54
+ width: 100% !important;
55
+ padding: 0 !important;
56
+ }
57
+
58
+ .sdoc-presentation-wrapper .sdoc-editor__article {
59
+ padding: calc(100vw / 794 * 40) calc(100vw / 794 * 60) !important;
60
+ font-size: calc(100vw / 794 * 14.7) !important;
61
+ }
62
+
63
+ .sdoc-presentation-wrapper .sdoc-checkbox-input {
64
+ width: calc(100vw / 794 * 13) !important;
65
+ }
66
+
67
+ .sdoc-presentation-wrapper .sdoc-code-block-pre {
68
+ font-size: calc(100vw / 794 * 13.3) !important;
69
+ }
70
+
37
71
  .sdoc-dropdown-print-container {
38
72
  display: flex;
39
73
  justify-content: space-between;
@@ -67,7 +67,7 @@ class Toaster {
67
67
  container.setAttribute('data-evergreen-toaster-container', '');
68
68
  document.body.appendChild(container);
69
69
  const root = (0, _client.createRoot)(container);
70
- root.render( /*#__PURE__*/_react.default.createElement(_toastManager.default, {
70
+ root.render(/*#__PURE__*/_react.default.createElement(_toastManager.default, {
71
71
  bindNotify: this._bindNotify,
72
72
  bindGetToasts: this._bindGetToasts,
73
73
  bindCloseAll: this._bindCloseAll
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ class ImageCache {
8
+ constructor() {
9
+ this.imageCache = null;
10
+ }
11
+ static saveImage(key, item) {
12
+ if (!this.imageCache) {
13
+ this.imageCache = new Map();
14
+ }
15
+ this.imageCache.set(key, item);
16
+ }
17
+ static getImage(key) {
18
+ if (!this.imageCache) {
19
+ this.imageCache = new Map();
20
+ }
21
+ return this.imageCache.get(key);
22
+ }
23
+ static deleteImage(key) {
24
+ if (!this.imageCache) {
25
+ this.imageCache = new Map();
26
+ }
27
+ this.imageCache.delete(key);
28
+ }
29
+ }
30
+ var _default = exports.default = ImageCache;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "2.0.41",
3
+ "version": "2.0.42-alph-0.0.1",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",
@@ -626,5 +626,6 @@
626
626
  "Insert_chart": "Insert chart",
627
627
  "Edit_chart": "Edit chart",
628
628
  "Please_complete_the_chart_configuration_first": "Please complete the chart configuration first",
629
- "chart": "chart"
629
+ "chart": "chart",
630
+ "Image_is_upload_error": "Image upload failed, please delete it and try again"
630
631
  }
@@ -622,5 +622,6 @@
622
622
  "Double_click_then_adjust_field_width": "双击后调节字段宽度",
623
623
  "Insert_chart": "插入图表",
624
624
  "Edit_chart": "编辑图表",
625
- "Please_complete_the_chart_configuration_first": "请先完成图表配置"
625
+ "Please_complete_the_chart_configuration_first": "请先完成图表配置",
626
+ "Image_is_upload_error": "图片上传失败,请删除后重新尝试"
626
627
  }
@@ -1,11 +1,11 @@
1
1
  @font-face {
2
2
  font-family: "sdocfont"; /* Project id 4097705 */
3
- src: url('iconfont.eot?t=1740817787686'); /* IE9 */
4
- src: url('iconfont.eot?t=1740817787686#iefix') format('embedded-opentype'), /* IE6-IE8 */
5
- url('iconfont.woff2?t=1740817787686') format('woff2'),
6
- url('iconfont.woff?t=1740817787686') format('woff'),
7
- url('iconfont.ttf?t=1740817787686') format('truetype'),
8
- url('iconfont.svg?t=1740817787686#sdocfont') format('svg');
3
+ src: url('iconfont.eot?t=1744104550669'); /* IE9 */
4
+ src: url('iconfont.eot?t=1744104550669#iefix') format('embedded-opentype'), /* IE6-IE8 */
5
+ url('iconfont.woff2?t=1744104550669') format('woff2'),
6
+ url('iconfont.woff?t=1744104550669') format('woff'),
7
+ url('iconfont.ttf?t=1744104550669') format('truetype'),
8
+ url('iconfont.svg?t=1744104550669#sdocfont') format('svg');
9
9
  }
10
10
 
11
11
  .sdocfont {
@@ -16,6 +16,14 @@
16
16
  -moz-osx-font-smoothing: grayscale;
17
17
  }
18
18
 
19
+ .sdoc-presentation:before {
20
+ content: "\e688";
21
+ }
22
+
23
+ .sdoc-close-presentation:before {
24
+ content: "\e689";
25
+ }
26
+
19
27
  .sdoc-seatable-row:before {
20
28
  content: "\e687";
21
29
  }
@@ -547,3 +555,4 @@
547
555
  .sdoc-user:before {
548
556
  content: "\e629";
549
557
  }
558
+
@@ -14,6 +14,10 @@
14
14
  />
15
15
  <missing-glyph />
16
16
 
17
+ <glyph glyph-name="sdoc-presentation" unicode="&#59016;" d="M128 96c-35.2 0-64 28.8-64 67.2V764.8h-16C22.4 764.8 0 787.2 0 816S22.4 864 48 864h928c25.6 0 48-22.4 48-48S1001.6 768 976 768H960v-601.6c0-35.2-28.8-67.2-64-67.2h-105.6c28.8-41.6 51.2-70.4 64-86.4 19.2-25.6 19.2-60.8-9.6-86.4-28.8-25.6-73.6-22.4-92.8 3.2s-118.4 166.4-121.6 169.6H384c-3.2-3.2-99.2-137.6-118.4-166.4s-64-32-86.4-12.8c-25.6 19.2-35.2 60.8-16 89.6 12.8 19.2 35.2 48 64 92.8L128 96zM160 768v-576h704V768H160zM409.6 656l268.8-163.2c9.6-6.4 9.6-22.4 0-28.8l-268.8-163.2c-9.6-6.4-25.6 0-25.6 12.8V643.2c0 12.8 12.8 19.2 25.6 12.8z" horiz-adv-x="1024" />
18
+
19
+ <glyph glyph-name="sdoc-close-presentation" unicode="&#59017;" d="M172.8 688c-188.8-185.6-188.8-489.6 0-675.2 188.8-185.6 492.8-185.6 678.4 0 188.8 185.6 188.8 489.6 0 675.2-12.8 16-35.2 19.2-54.4 16-19.2-6.4-35.2-19.2-41.6-41.6-6.4-19.2 0-41.6 16-54.4 144-144 144-374.4 0-515.2-144-144-374.4-144-518.4 0-144 140.8-144 371.2 0 515.2 12.8 12.8 19.2 35.2 16 54.4-6.4 19.2-22.4 35.2-41.6 38.4-19.2 6.4-41.6 0-54.4-12.8zM512 896c35.2 0 64-28.8 64-64v-384c0-35.2-28.8-64-64-64s-64 28.8-64 64V832c0 35.2 28.8 64 64 64z" horiz-adv-x="1024" />
20
+
17
21
  <glyph glyph-name="sdoc-seatable-row" unicode="&#59015;" d="M0 528L256 384l-256-144v288zM0 64h1024v-96H0v96z m320 368h704v-96H320v96zM0 800h1024v-96H0V800z" horiz-adv-x="1024" />
18
22
 
19
23
  <glyph glyph-name="sdoc-ask-ai" unicode="&#59013;" d="M678.4 896l92.8-252.8 252.8-92.8-252.8-92.8-92.8-252.8-92.8 252.8-252.8 92.8c166.4 60.8 252.8 92.8 252.8 92.8L678.4 896zM185.6 198.4L256 384l70.4-185.6L512 128l-185.6-70.4L256-128l-70.4 185.6L0 128z" horiz-adv-x="1024" />
@@ -1,14 +1,11 @@
1
1
  @font-face {
2
- font-family: "sdocfont";
3
- /* Project id 4097705 */
4
- src: url('./sdoc-editor-font/iconfont.eot?t=1740817787686');
5
- /* IE9 */
6
- src: url('./sdoc-editor-font/iconfont.eot?t=1740817787686#iefix') format('embedded-opentype'),
7
- /* IE6-IE8 */
8
- url('./sdoc-editor-font/iconfont.woff2?t=1740817787686') format('woff2'),
9
- url('./sdoc-editor-font/iconfont.woff?t=1740817787686') format('woff'),
10
- url('./sdoc-editor-font/iconfont.ttf?t=1740817787686') format('truetype'),
11
- url('./sdoc-editor-font/iconfont.svg?t=1740817787686#sdocfont') format('svg');
2
+ font-family: "sdocfont"; /* Project id 4097705 */
3
+ src: url('./sdoc-editor-font/iconfont.eot?t=1744104550669'); /* IE9 */
4
+ src: url('./sdoc-editor-font/iconfont.eot?t=1744104550669#iefix') format('embedded-opentype'), /* IE6-IE8 */
5
+ url('./sdoc-editor-font/iconfont.woff2?t=1744104550669') format('woff2'),
6
+ url('./sdoc-editor-font/iconfont.woff?t=1744104550669') format('woff'),
7
+ url('./sdoc-editor-font/iconfont.ttf?t=1744104550669') format('truetype'),
8
+ url('./sdoc-editor-font/iconfont.svg?t=1744104550669#sdocfont') format('svg');
12
9
  }
13
10
 
14
11
  .sdocfont {
@@ -19,6 +16,14 @@
19
16
  -moz-osx-font-smoothing: grayscale;
20
17
  }
21
18
 
19
+ .sdoc-presentation:before {
20
+ content: "\e688";
21
+ }
22
+
23
+ .sdoc-close-presentation:before {
24
+ content: "\e689";
25
+ }
26
+
22
27
  .sdoc-seatable-row:before {
23
28
  content: "\e687";
24
29
  }
@@ -550,3 +555,4 @@
550
555
  .sdoc-user:before {
551
556
  content: "\e629";
552
557
  }
558
+