@seafile/sdoc-editor 0.1.143 → 0.1.145
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.
- package/dist/basic-sdk/extension/plugins/table/render/index.css +6 -2
- package/dist/basic-sdk/layout/article-container.js +17 -19
- package/dist/basic-sdk/socket/socket-client.js +18 -22
- package/dist/basic-sdk/socket/socket-manager.js +25 -10
- package/dist/basic-sdk/utils/debug.js +13 -4
- package/package.json +3 -2
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
.sdoc-table-wrapper {
|
|
2
2
|
width: 100%;
|
|
3
|
-
|
|
3
|
+
margin: 16px 0;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.sdoc-table-wrapper + .sdoc-table-wrapper {
|
|
7
|
+
margin-top: 32px;
|
|
4
8
|
}
|
|
5
9
|
|
|
6
10
|
.sdoc-table-wrapper .sdoc-table-scroll-wrapper {
|
|
@@ -51,8 +55,8 @@
|
|
|
51
55
|
padding: 10px 10px;
|
|
52
56
|
border-right: 1px solid #ccc;
|
|
53
57
|
border-bottom: 1px solid #ccc;
|
|
54
|
-
word-break: break-all;
|
|
55
58
|
line-height: 1.5;
|
|
59
|
+
vertical-align: top;
|
|
56
60
|
}
|
|
57
61
|
|
|
58
62
|
.sdoc-table-wrapper .table-row:first-child .table-cell {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
|
2
2
|
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
3
|
-
import React, { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { useScrollContext } from '../hooks/use-scroll-context';
|
|
5
5
|
export default function ArticleContainer(_ref) {
|
|
6
6
|
var editor = _ref.editor,
|
|
7
|
-
readOnly = _ref.readOnly,
|
|
8
7
|
children = _ref.children;
|
|
9
8
|
var articleRef = useRef(null);
|
|
10
9
|
useEffect(function () {
|
|
@@ -16,24 +15,26 @@ export default function ArticleContainer(_ref) {
|
|
|
16
15
|
_useState2 = _slicedToArray(_useState, 2),
|
|
17
16
|
containerStyle = _useState2[0],
|
|
18
17
|
setContainerStyle = _useState2[1];
|
|
18
|
+
var handleWindowResize = useCallback(function () {
|
|
19
|
+
var rect = scrollRef.current.getBoundingClientRect();
|
|
20
|
+
var articleRect = articleRef.current.getBoundingClientRect();
|
|
21
|
+
if ((rect.width - articleRect.width) / 2 < 280) {
|
|
22
|
+
setContainerStyle({
|
|
23
|
+
marginLeft: '280px'
|
|
24
|
+
});
|
|
25
|
+
} else {
|
|
26
|
+
setContainerStyle({});
|
|
27
|
+
}
|
|
28
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
29
|
+
}, []);
|
|
19
30
|
useEffect(function () {
|
|
20
|
-
|
|
21
|
-
var handleWindowResize = function handleWindowResize() {
|
|
22
|
-
var rect = scrollRef.current.getBoundingClientRect();
|
|
23
|
-
var articleRect = articleRef.current.getBoundingClientRect();
|
|
24
|
-
if ((rect.width - articleRect.width) / 2 < 280) {
|
|
25
|
-
setContainerStyle({
|
|
26
|
-
marginLeft: '280px'
|
|
27
|
-
});
|
|
28
|
-
} else {
|
|
29
|
-
setContainerStyle({});
|
|
30
|
-
}
|
|
31
|
-
};
|
|
31
|
+
handleWindowResize();
|
|
32
32
|
window.addEventListener('resize', handleWindowResize);
|
|
33
33
|
return function () {
|
|
34
34
|
window.removeEventListener('resize', handleWindowResize);
|
|
35
35
|
};
|
|
36
|
-
|
|
36
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
37
|
+
}, []);
|
|
37
38
|
return /*#__PURE__*/React.createElement("div", {
|
|
38
39
|
className: "sdoc-article-container",
|
|
39
40
|
style: containerStyle
|
|
@@ -44,7 +45,4 @@ export default function ArticleContainer(_ref) {
|
|
|
44
45
|
className: "article",
|
|
45
46
|
ref: articleRef
|
|
46
47
|
}, children[0]), _toConsumableArray(children.slice(1))));
|
|
47
|
-
}
|
|
48
|
-
ArticleContainer.defaultProps = {
|
|
49
|
-
readOnly: false
|
|
50
|
-
};
|
|
48
|
+
}
|
|
@@ -3,7 +3,7 @@ import _createClass from "@babel/runtime/helpers/esm/createClass";
|
|
|
3
3
|
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
|
|
4
4
|
import io from 'socket.io-client';
|
|
5
5
|
import SocketManager from './socket-manager';
|
|
6
|
-
import
|
|
6
|
+
import { clientDebug, serverDebug } from '../utils/debug';
|
|
7
7
|
var SocketClient = /*#__PURE__*/_createClass(function SocketClient(config) {
|
|
8
8
|
var _this = this;
|
|
9
9
|
_classCallCheck(this, SocketClient);
|
|
@@ -38,45 +38,33 @@ var SocketClient = /*#__PURE__*/_createClass(function SocketClient(config) {
|
|
|
38
38
|
});
|
|
39
39
|
};
|
|
40
40
|
this.onReconnect = function (data) {
|
|
41
|
-
|
|
41
|
+
clientDebug('reconnect.');
|
|
42
42
|
_this.isReconnect = true;
|
|
43
43
|
var socketManager = SocketManager.getInstance();
|
|
44
44
|
socketManager.dispatchConnectState('reconnect');
|
|
45
45
|
};
|
|
46
46
|
this.onReconnectAttempt = function (attemptNumber) {
|
|
47
|
-
|
|
47
|
+
clientDebug('reconnect_attempt. %s', attemptNumber);
|
|
48
48
|
var socketManager = SocketManager.getInstance();
|
|
49
49
|
socketManager.dispatchConnectState('reconnect_attempt', attemptNumber);
|
|
50
50
|
};
|
|
51
51
|
this.onReconnectError = function () {
|
|
52
|
-
|
|
52
|
+
clientDebug('reconnect_error.');
|
|
53
53
|
var socketManager = SocketManager.getInstance();
|
|
54
54
|
socketManager.dispatchConnectState('reconnect_error');
|
|
55
55
|
};
|
|
56
56
|
this.onDisconnected = function (data) {
|
|
57
|
-
|
|
57
|
+
clientDebug('disconnect message: %s', data);
|
|
58
58
|
var socketManager = SocketManager.getInstance();
|
|
59
59
|
socketManager.dispatchConnectState('disconnect');
|
|
60
60
|
};
|
|
61
61
|
this.onConnectError = function () {
|
|
62
|
-
|
|
62
|
+
clientDebug('connect_error.');
|
|
63
63
|
var socketManager = SocketManager.getInstance();
|
|
64
64
|
socketManager.dispatchConnectState('connect_error');
|
|
65
65
|
};
|
|
66
|
-
this.onJoinRoom = function (userInfo) {
|
|
67
|
-
debug('%s joined room success.', userInfo.username);
|
|
68
|
-
var socketManager = SocketManager.getInstance();
|
|
69
|
-
socketManager.dispatchConnectState('join-room', userInfo);
|
|
70
|
-
};
|
|
71
|
-
this.onLeaveRoom = function (username) {
|
|
72
|
-
debug('%s leaved room success.', username);
|
|
73
|
-
var socketManager = SocketManager.getInstance();
|
|
74
|
-
socketManager.dispatchConnectState('leave-room', username);
|
|
75
|
-
};
|
|
76
66
|
this.sendOperations = function (operations, version, selection, callback) {
|
|
77
|
-
|
|
78
|
-
debug('%O', operations);
|
|
79
|
-
debug('======================================');
|
|
67
|
+
clientDebug('send operations: %O', operations);
|
|
80
68
|
_this.socket.emit('update-document', _this.getParams({
|
|
81
69
|
operations: operations,
|
|
82
70
|
version: version,
|
|
@@ -85,14 +73,22 @@ var SocketClient = /*#__PURE__*/_createClass(function SocketClient(config) {
|
|
|
85
73
|
callback && callback(result);
|
|
86
74
|
});
|
|
87
75
|
};
|
|
76
|
+
this.onJoinRoom = function (userInfo) {
|
|
77
|
+
serverDebug('%s joined room success.', userInfo.username);
|
|
78
|
+
var socketManager = SocketManager.getInstance();
|
|
79
|
+
socketManager.dispatchConnectState('join-room', userInfo);
|
|
80
|
+
};
|
|
81
|
+
this.onLeaveRoom = function (username) {
|
|
82
|
+
serverDebug('%s leaved room success.', username);
|
|
83
|
+
var socketManager = SocketManager.getInstance();
|
|
84
|
+
socketManager.dispatchConnectState('leave-room', username);
|
|
85
|
+
};
|
|
88
86
|
/**
|
|
89
87
|
* receive remote broadcast operations
|
|
90
88
|
* @param {*} params {operations, version}
|
|
91
89
|
*/
|
|
92
90
|
this.onReceiveRemoteOperations = function (params) {
|
|
93
|
-
|
|
94
|
-
debug('%O', params);
|
|
95
|
-
debug('**************************************');
|
|
91
|
+
serverDebug('receive operations: %O', params);
|
|
96
92
|
var socketManager = SocketManager.getInstance();
|
|
97
93
|
socketManager.onReceiveRemoteOperations(params);
|
|
98
94
|
};
|
|
@@ -5,7 +5,7 @@ var _class;
|
|
|
5
5
|
import EventBus from '../utils/event-bus';
|
|
6
6
|
import { syncRemoteOperations, reExecRevertOperationList, revertOperationList, syncRemoteCursorLocation } from './helpers';
|
|
7
7
|
import SocketClient from './socket-client';
|
|
8
|
-
import
|
|
8
|
+
import { conflictDebug, serverDebug, stateDebug } from '../utils/debug';
|
|
9
9
|
import { deleteCursor } from '../cursor/helper';
|
|
10
10
|
|
|
11
11
|
// idle --> sending --> conflict --> idle
|
|
@@ -35,12 +35,14 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
35
35
|
};
|
|
36
36
|
this.sendOperations = function () {
|
|
37
37
|
if (_this.state !== STATE.IDLE) return;
|
|
38
|
+
stateDebug("State changed: ".concat(_this.state, " -> ").concat(STATE.SENDING));
|
|
38
39
|
_this.state = STATE.SENDING;
|
|
39
40
|
_this.sendNextOperations();
|
|
40
41
|
};
|
|
41
42
|
this.sendNextOperations = function () {
|
|
42
43
|
if (_this.state !== STATE.SENDING) return;
|
|
43
44
|
if (_this.pendingOperationList.length === 0) {
|
|
45
|
+
stateDebug("State Changed: ".concat(_this.state, " -> ").concat(STATE.IDLE));
|
|
44
46
|
_this.state = STATE.IDLE;
|
|
45
47
|
return;
|
|
46
48
|
}
|
|
@@ -72,11 +74,13 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
72
74
|
_this.dispatchConnectState(error_type);
|
|
73
75
|
|
|
74
76
|
// reset sending control
|
|
77
|
+
stateDebug("State Changed: ".concat(_this.state, " -> ").concat(STATE.NEED_RELOAD));
|
|
75
78
|
_this.state = STATE.NEED_RELOAD;
|
|
76
79
|
_this._sendingOperations = null;
|
|
77
80
|
} else if (error_type === 'version_behind_server') {
|
|
78
81
|
// Put the failed operation into the pending list and re-execute it
|
|
79
82
|
_this.pendingOperationList.unshift(_toConsumableArray(_this._sendingOperations));
|
|
83
|
+
stateDebug("State Changed: ".concat(_this.state, " -> ").concat(STATE.CONFLICT));
|
|
80
84
|
_this.state = STATE.CONFLICT;
|
|
81
85
|
var lose_operations = result.lose_operations;
|
|
82
86
|
_this.resolveConflicting(lose_operations);
|
|
@@ -108,13 +112,13 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
108
112
|
if (serverVersion === clientVersion + 1) {
|
|
109
113
|
// update execute remote operations flag
|
|
110
114
|
_this.editor.isRemote = true;
|
|
111
|
-
debug('Editor isRemote is true: %s', _this.editor.isRemote);
|
|
112
115
|
var operations = params.operations;
|
|
113
116
|
// Update content & version
|
|
114
|
-
|
|
117
|
+
serverDebug('execute remote operations: %O', operations);
|
|
115
118
|
try {
|
|
116
119
|
syncRemoteOperations(_this.editor, operations);
|
|
117
120
|
} catch (error) {
|
|
121
|
+
stateDebug("State Changed: ".concat(_this.state, " -> ").concat(STATE.CONFLICT));
|
|
118
122
|
_this.state = STATE.CONFLICT;
|
|
119
123
|
_this.dispatchConnectState('sync_server_operations_error');
|
|
120
124
|
return;
|
|
@@ -138,28 +142,34 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
138
142
|
// The client version is inconsistent with the server version, and the latest operations performed by the server need to be loaded
|
|
139
143
|
if (serverVersion !== clientVersion) {
|
|
140
144
|
_this.onConflictHappen();
|
|
145
|
+
return;
|
|
141
146
|
}
|
|
142
147
|
|
|
143
148
|
// The version consistency indicates that there is no conflict and no processing is required
|
|
149
|
+
stateDebug("State Changed: ".concat(_this.state, " -> ").concat(STATE.IDLE));
|
|
144
150
|
_this.state = STATE.IDLE;
|
|
145
151
|
};
|
|
146
152
|
this.onConflictHappen = function () {
|
|
153
|
+
stateDebug("State Changed: ".concat(_this.state, " -> ").concat(STATE.CONFLICT));
|
|
147
154
|
_this.state = STATE.CONFLICT;
|
|
148
155
|
_this.socketClient.getRecentOperations();
|
|
149
156
|
};
|
|
150
157
|
this.onGetRecentOperations = function (result) {
|
|
151
158
|
var mode = result.mode,
|
|
152
159
|
content = result.content;
|
|
160
|
+
conflictDebug('Start conflict resolution');
|
|
153
161
|
// sync document
|
|
154
162
|
if (mode === 'document') {
|
|
155
163
|
var version = content.version,
|
|
156
164
|
children = content.children;
|
|
157
165
|
// 1. update document
|
|
166
|
+
conflictDebug('Update local document to remote document');
|
|
158
167
|
_this.document.children = children;
|
|
159
168
|
_this.document.version = version;
|
|
160
169
|
_this.editor.children = children;
|
|
161
170
|
_this.editor.isRemote = true;
|
|
162
171
|
_this.editor.onChange();
|
|
172
|
+
stateDebug("State Changed: ".concat(_this.state, " -> ").concat(STATE.IDLE));
|
|
163
173
|
_this.editor.isRemote = false;
|
|
164
174
|
_this.state = STATE.IDLE;
|
|
165
175
|
_this._sendingOperations = null;
|
|
@@ -169,7 +179,7 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
169
179
|
_this.pendingOperationList = [];
|
|
170
180
|
|
|
171
181
|
// need resend this operations to server
|
|
172
|
-
|
|
182
|
+
conflictDebug('Re-execute local unsynchronized operations: %o', pendingOperationList);
|
|
173
183
|
reExecRevertOperationList(_this.editor, pendingOperationList);
|
|
174
184
|
return;
|
|
175
185
|
}
|
|
@@ -180,8 +190,8 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
180
190
|
_this.resolveConflicting(loseOperations);
|
|
181
191
|
};
|
|
182
192
|
this.resolveConflicting = function (loseOperations) {
|
|
193
|
+
conflictDebug('resolve conflicts');
|
|
183
194
|
_this.editor.isRemote = true;
|
|
184
|
-
debug('Editor isRemote is true: %s', _this.editor.isRemote);
|
|
185
195
|
if (_this.pendingOperationList.length !== 0) {
|
|
186
196
|
// 1. Revert operations
|
|
187
197
|
// 1.1 record reverted operationList & clear pendingOperationList
|
|
@@ -189,23 +199,24 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
189
199
|
_this.pendingOperationList = [];
|
|
190
200
|
|
|
191
201
|
// 1.2 Revert operationList
|
|
192
|
-
|
|
202
|
+
conflictDebug('revert locale operations: %O', _this.revertOperationList);
|
|
193
203
|
revertOperationList(_this.editor, _this.revertOperationList);
|
|
194
204
|
}
|
|
195
205
|
loseOperations = loseOperations.sort(function (prev, next) {
|
|
196
206
|
return prev.version - next.version;
|
|
197
207
|
});
|
|
198
|
-
|
|
208
|
+
conflictDebug('lose operations length: %s', loseOperations.length);
|
|
199
209
|
while (loseOperations.length > 0) {
|
|
200
210
|
var operationParams = loseOperations.shift();
|
|
201
211
|
// 2. execute operations
|
|
202
212
|
var operations = operationParams.operations,
|
|
203
213
|
serverVersion = operationParams.version;
|
|
204
214
|
// 2.1 Update content & version
|
|
205
|
-
|
|
215
|
+
conflictDebug('execute lose operations: %O', operations);
|
|
206
216
|
try {
|
|
207
217
|
syncRemoteOperations(_this.editor, operations);
|
|
208
218
|
} catch (error) {
|
|
219
|
+
stateDebug("State Changed: ".concat(_this.state, " -> ").concat(STATE.CONFLICT));
|
|
209
220
|
_this.state = STATE.CONFLICT;
|
|
210
221
|
_this.dispatchConnectState('sync_server_operations_error');
|
|
211
222
|
return;
|
|
@@ -218,6 +229,7 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
218
229
|
if (_this.revertOperationList.length === 0) {
|
|
219
230
|
Promise.resolve().then(function () {
|
|
220
231
|
_this.editor.isRemote = false;
|
|
232
|
+
stateDebug("State Changed: ".concat(_this.state, " -> ").concat(STATE.IDLE));
|
|
221
233
|
_this.state = STATE.IDLE;
|
|
222
234
|
_this._sendingOperations = null;
|
|
223
235
|
_this.revertOperationList = [];
|
|
@@ -229,17 +241,19 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
229
241
|
Promise.resolve().then(function () {
|
|
230
242
|
// reset execute remote operations flag
|
|
231
243
|
_this.editor.isRemote = false;
|
|
244
|
+
stateDebug("State Changed: ".concat(_this.state, " -> ").concat(STATE.IDLE));
|
|
232
245
|
_this.state = STATE.IDLE;
|
|
233
246
|
_this._sendingOperations = null;
|
|
234
247
|
|
|
235
248
|
// 3. Execute pending operations
|
|
236
249
|
// 3.1 Re-execute operations
|
|
237
|
-
|
|
238
|
-
|
|
250
|
+
conflictDebug('Editor isRemote is false: %s', _this.editor.isRemote);
|
|
251
|
+
conflictDebug('Re-execute pending operations, %O', _this.revertOperationList);
|
|
239
252
|
reExecRevertOperationList(_this.editor, _this.revertOperationList);
|
|
240
253
|
|
|
241
254
|
// 3.2 Clear revert operationList
|
|
242
255
|
_this.revertOperationList = [];
|
|
256
|
+
conflictDebug('Complete conflict resolution');
|
|
243
257
|
});
|
|
244
258
|
};
|
|
245
259
|
this.sendCursorLocation = function (location) {
|
|
@@ -262,6 +276,7 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
262
276
|
_this.pendingOperationList.unshift(_this._sendingOperations.slice());
|
|
263
277
|
_this._sendingOperations = null;
|
|
264
278
|
}
|
|
279
|
+
stateDebug("State Changed: ".concat(_this.state, " -> ").concat(STATE.IDLE));
|
|
265
280
|
_this.state = STATE.DISCONNECT;
|
|
266
281
|
}
|
|
267
282
|
_this.eventBus.dispatch(type, message);
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import Debug from 'debug';
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
var stateDebug = Debug('sdoc:state-change');
|
|
3
|
+
stateDebug.enabled = true;
|
|
4
|
+
stateDebug.log = console.log;
|
|
5
|
+
var clientDebug = Debug('sdoc:socket-client');
|
|
6
|
+
clientDebug.enabled = true;
|
|
7
|
+
clientDebug.log = console.log;
|
|
8
|
+
var serverDebug = Debug('sdoc:socket-server');
|
|
9
|
+
serverDebug.enabled = true;
|
|
10
|
+
serverDebug.log = console.log;
|
|
11
|
+
var conflictDebug = Debug('sdoc:sdoc-conflict');
|
|
12
|
+
conflictDebug.enabled = true;
|
|
13
|
+
conflictDebug.log = console.log;
|
|
14
|
+
export { stateDebug, clientDebug, serverDebug, conflictDebug };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seafile/sdoc-editor",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.145",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "This is a sdoc editor",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"clean-webpack-plugin": "4.0.0",
|
|
70
70
|
"core-js": "2.6.12",
|
|
71
71
|
"css-loader": "^3.2.1",
|
|
72
|
+
"css-minimizer-webpack-plugin": "5.0.1",
|
|
72
73
|
"dayjs": "1.11.2",
|
|
73
74
|
"dotenv": "6.2.0",
|
|
74
75
|
"dotenv-expand": "5.1.0",
|
|
@@ -94,9 +95,9 @@
|
|
|
94
95
|
"koa": "2.13.4",
|
|
95
96
|
"koa-router": "7.3.0",
|
|
96
97
|
"koa-send": "5.0.1",
|
|
98
|
+
"koa2-cors": "2.0.6",
|
|
97
99
|
"mini-css-extract-plugin": "^1.3.5",
|
|
98
100
|
"object-assign": "4.1.1",
|
|
99
|
-
"css-minimizer-webpack-plugin":"5.0.1",
|
|
100
101
|
"pnp-webpack-plugin": "1.5.0",
|
|
101
102
|
"postcss": "^7.0.0",
|
|
102
103
|
"postcss-flexbugs-fixes": "^4.1.0",
|