@seafile/sdoc-editor 0.5.55 → 0.5.56

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.
@@ -41,6 +41,9 @@
41
41
  width: 100%;
42
42
  }
43
43
 
44
+ .sdoc-editor-container.mobile .sdoc-editor-content.readonly.no-outline {
45
+ min-width: 100%;
46
+ }
44
47
 
45
48
  .sdoc-editor-container .sdoc-scroll-container {
46
49
  z-index: 100;
@@ -8,6 +8,6 @@
8
8
  }
9
9
 
10
10
  .sdoc-editor-container.mobile .sdoc-editor-content.readonly .article {
11
- width: 100% !important;
11
+ width: 100vw !important;
12
12
  padding: 1rem;
13
13
  }
@@ -1,9 +1,9 @@
1
1
  import React, { useCallback, useMemo, Fragment } from 'react';
2
2
  import { Editable, ReactEditor, Slate } from '@seafile/slate-react';
3
- import { Editor, Node, Range } from '@seafile/slate';
3
+ import { Editor, Node, Transforms } from '@seafile/slate';
4
4
  import scrollIntoView from 'scroll-into-view-if-needed';
5
5
  import { renderLeaf, renderElement, ContextToolbar, SideToolbar } from '../extension';
6
- import { getAboveBlockNode, getNextNode, getPrevNode, isSelectionAtBlockEnd, isSelectionAtBlockStart } from '../extension/core';
6
+ import { getAboveBlockNode, getNextNode, getPrevNode, isSelectionAtBlockEnd, isSelectionAtBlockStart, getCurrentNode, isCurrentLineEmpty, isCurrentLineHasText } from '../extension/core';
7
7
  import EventProxy from '../utils/event-handler';
8
8
  import { useCursors } from '../cursor/use-cursors';
9
9
  import { INTERNAL_EVENT } from '../constants';
@@ -14,7 +14,7 @@ import EventBus from '../utils/event-bus';
14
14
  import { ArticleContainer } from '../layout';
15
15
  import { useScrollContext } from '../hooks/use-scroll-context';
16
16
  import { SetNodeToDecorations } from '../highlight';
17
- import { IMAGE, IMAGE_BLOCK } from '../extension/constants';
17
+ import { IMAGE, IMAGE_BLOCK, CODE_LINE } from '../extension/constants';
18
18
  import { isPreventResetTableSelectedRange } from '../extension/plugins/table/helpers';
19
19
  const EditableArticle = _ref => {
20
20
  let {
@@ -83,6 +83,39 @@ const EditableArticle = _ref => {
83
83
  return;
84
84
  }
85
85
  if (event.key === 'Backspace') {
86
+ const [currentNode] = getCurrentNode(editor);
87
+ let prevNode = null;
88
+ let prevPath = null;
89
+ if (getPrevNode(editor)) {
90
+ [prevNode, prevPath] = getPrevNode(editor);
91
+ }
92
+ // If the cursor is at the beginning, and the current line is not empty, is not a CODE_LINE, and the previous line is a CODE_LINE.
93
+ if (prevNode && isSelectionAtBlockStart(editor) && !isCurrentLineEmpty(editor) && prevNode.type === CODE_LINE && currentNode.type !== CODE_LINE) {
94
+ if (!isCurrentLineHasText(currentNode)) {
95
+ const prevNodeText = Node.string(prevNode);
96
+ Transforms.removeNodes(editor, {
97
+ at: prevPath
98
+ });
99
+ Transforms.insertText(editor, prevNodeText);
100
+ event.preventDefault();
101
+ } else {
102
+ const path = prevPath;
103
+ path[path.length] = 0;
104
+ const end = prevNode.children[0].text.length;
105
+ const range = {
106
+ anchor: {
107
+ path,
108
+ offset: end
109
+ },
110
+ focus: {
111
+ path,
112
+ offset: end
113
+ }
114
+ };
115
+ Transforms.select(editor, range);
116
+ event.preventDefault();
117
+ }
118
+ }
86
119
  const {
87
120
  y
88
121
  } = getCursorPosition();
@@ -250,6 +250,15 @@ export const getPrevNode = editor => {
250
250
  }
251
251
  return prevNode;
252
252
  };
253
+ export const getCurrentNode = editor => {
254
+ if (!editor.selection) return null;
255
+ const [nodeEntry] = Editor.nodes(editor, {
256
+ at: editor.selection,
257
+ match: n => Element.isElement(n) && Editor.isBlock(editor, n),
258
+ mode: 'lowest'
259
+ });
260
+ return nodeEntry || null;
261
+ };
253
262
  export const getNextNode = editor => {
254
263
  const [lowerNode, lowerPath] = getAboveNode(editor, {
255
264
  mode: 'lowest',
@@ -423,4 +432,18 @@ export const isHasImg = editor => {
423
432
  }
424
433
  }
425
434
  return hasImg;
435
+ };
436
+ export const isCurrentLineEmpty = editor => {
437
+ const {
438
+ selection
439
+ } = editor;
440
+ if (!selection || !ReactEditor.isFocused(editor)) return false;
441
+ const [node] = Editor.node(editor, selection.focus.path.slice(0, -1));
442
+ if (Element.isElement(node)) {
443
+ return node.children.every(child => Element.isElement(child) ? false : Node.string(child) === '');
444
+ }
445
+ return true;
446
+ };
447
+ export const isCurrentLineHasText = node => {
448
+ return Node.string(node).trim() !== '';
426
449
  };
@@ -37,6 +37,11 @@ const withCheckList = editor => {
37
37
  Transforms.splitNodes(editor, {
38
38
  always: true
39
39
  });
40
+ Transforms.setNodes(editor, {
41
+ checked: false
42
+ }, {
43
+ at: node[1]
44
+ });
40
45
  return;
41
46
  }
42
47
  insertBreak();
@@ -36,46 +36,31 @@ const RevisionOperations = _ref => {
36
36
  if (!isSdocRevision) return;
37
37
  if (isShowChanges) return;
38
38
  if (isPublished) return;
39
- setShowTip(true);
40
- setTipType(TIP_TYPE.CHECKING);
41
-
42
- // Let users perceive the processing process
43
- let timer = null;
44
- timer = setTimeout(() => {
45
- const revisionPromise = loadDocument();
46
- const baseVersionPromise = context.getRevisionBaseVersionContent();
47
- const originVersionPromise = context.getSeadocOriginFileContent();
48
- Promise.all([revisionPromise, baseVersionPromise, originVersionPromise]).then(results => {
49
- const [revisionContent, baseRes, masterRes] = results;
50
- const baseContent = JSON.parse(baseRes.data.content);
51
- const masterContent = JSON.parse(masterRes.data.content);
52
- timer = null;
39
+ const revisionPromise = loadDocument();
40
+ const baseVersionPromise = context.getRevisionBaseVersionContent();
41
+ const originVersionPromise = context.getSeadocOriginFileContent();
42
+ Promise.all([revisionPromise, baseVersionPromise, originVersionPromise]).then(results => {
43
+ const [revisionContent, baseRes, masterRes] = results;
44
+ const baseContent = JSON.parse(baseRes.data.content);
45
+ const masterContent = JSON.parse(masterRes.data.content);
53
46
 
54
- // no changes
55
- if (masterContent.version === baseContent.version) {
56
- setShowTip(false);
57
- setTipType('');
58
- return;
59
- }
60
- const {
61
- value
62
- } = getRebase(masterContent, baseContent, revisionContent);
63
- setMergeValue(value);
64
- setTipType(TIP_TYPE.SOURCE_DOCUMENT_CHANGED);
65
- }).catch(error => {
66
- timer = null;
67
- if (typeof error === 'string') {
68
- toaster.danger(t(error));
69
- return;
70
- }
71
- toaster.danger(t('Error'));
72
- setShowTip(false);
73
- setTipType('');
74
- });
75
- }, 600);
76
- return () => {
77
- timer && clearTimeout(timer);
78
- };
47
+ // no changes
48
+ if (masterContent.version === baseContent.version) return;
49
+ setShowTip(true);
50
+ const {
51
+ value
52
+ } = getRebase(masterContent, baseContent, revisionContent);
53
+ setMergeValue(value);
54
+ setTipType(TIP_TYPE.SOURCE_DOCUMENT_CHANGED);
55
+ }).catch(error => {
56
+ if (typeof error === 'string') {
57
+ toaster.danger(t(error));
58
+ return;
59
+ }
60
+ toaster.danger(t('Error'));
61
+ setShowTip(false);
62
+ setTipType('');
63
+ });
79
64
  // eslint-disable-next-line react-hooks/exhaustive-deps
80
65
  }, []);
81
66
  const onDocumentReplaced = useCallback(() => {
@@ -4,7 +4,7 @@ import { SDocViewer } from '../basic-sdk';
4
4
  import context from '../context';
5
5
  import Loading from '../components/loading';
6
6
  import Layout, { Header, Content } from '../layout';
7
- import { generateDefaultDocContent } from '../utils';
7
+ import { generateDefaultDocContent, isMobile } from '../utils';
8
8
  import ErrorBoundary from './error-boundary';
9
9
  import '../assets/css/simple-viewer.css';
10
10
  class SimpleViewer extends React.Component {
@@ -64,6 +64,26 @@ class SimpleViewer extends React.Component {
64
64
  sharePermissionText,
65
65
  downloadURL
66
66
  } = context.getSettings();
67
+ if (isMobile) {
68
+ return /*#__PURE__*/React.createElement(ErrorBoundary, null, /*#__PURE__*/React.createElement(Layout, null, /*#__PURE__*/React.createElement(Header, null, /*#__PURE__*/React.createElement("div", {
69
+ className: "doc-info"
70
+ }, /*#__PURE__*/React.createElement("h2", {
71
+ className: "doc-name my-0"
72
+ }, docName), sharePermissionText && /*#__PURE__*/React.createElement("span", {
73
+ className: "sdoc-share-permission ml-2"
74
+ }, sharePermissionText)), /*#__PURE__*/React.createElement("div", {
75
+ className: "doc-ops"
76
+ }, downloadURL && /*#__PURE__*/React.createElement("a", {
77
+ href: downloadURL,
78
+ className: "op-item"
79
+ }, /*#__PURE__*/React.createElement("i", {
80
+ className: "sdocfont sdoc-download"
81
+ })))), /*#__PURE__*/React.createElement(Content, null, /*#__PURE__*/React.createElement(SDocViewer, {
82
+ document: document,
83
+ showToolbar: false,
84
+ showOutline: false
85
+ }))));
86
+ }
67
87
  return /*#__PURE__*/React.createElement(ErrorBoundary, null, /*#__PURE__*/React.createElement(Layout, null, /*#__PURE__*/React.createElement(Header, null, /*#__PURE__*/React.createElement("div", {
68
88
  className: "doc-info"
69
89
  }, /*#__PURE__*/React.createElement("h2", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "0.5.55",
3
+ "version": "0.5.56",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",