@seafile/sdoc-editor 0.1.118 → 0.1.120
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/socket/socket-client.js +7 -10
- package/dist/basic-sdk/socket/socket-manager.js +150 -146
- package/dist/basic-sdk/socket/with-socket-io.js +1 -1
- package/dist/components/tip-message/index.js +28 -19
- package/package.json +1 -1
- package/public/locales/en/sdoc-editor.json +3 -3
- package/public/locales/zh-CN/sdoc-editor.json +3 -3
|
@@ -25,11 +25,8 @@ var SocketClient = /*#__PURE__*/_createClass(function SocketClient(config) {
|
|
|
25
25
|
// sync operations or document
|
|
26
26
|
if (_this.isReconnect) {
|
|
27
27
|
_this.isReconnect = false;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (serverVersion !== clientVersion) {
|
|
31
|
-
_this.syncDocumentBySocket();
|
|
32
|
-
}
|
|
28
|
+
// The reconnect of socketManager needs to be triggered after entering the room again
|
|
29
|
+
socketManager.onReconnect(result);
|
|
33
30
|
}
|
|
34
31
|
socketManager.dispatchConnectState('onConnected', result);
|
|
35
32
|
return;
|
|
@@ -92,14 +89,14 @@ var SocketClient = /*#__PURE__*/_createClass(function SocketClient(config) {
|
|
|
92
89
|
* receive remote broadcast operations
|
|
93
90
|
* @param {*} params {operations, version}
|
|
94
91
|
*/
|
|
95
|
-
this.
|
|
92
|
+
this.onReceiveRemoteOperations = function (params) {
|
|
96
93
|
debug('********* receive operations *********');
|
|
97
94
|
debug('%O', params);
|
|
98
95
|
debug('**************************************');
|
|
99
96
|
var socketManager = SocketManager.getInstance();
|
|
100
|
-
socketManager.
|
|
97
|
+
socketManager.onReceiveRemoteOperations(params);
|
|
101
98
|
};
|
|
102
|
-
this.
|
|
99
|
+
this.getRecentOperations = function () {
|
|
103
100
|
var docUuid = _this.config.docUuid;
|
|
104
101
|
var socketManager = SocketManager.getInstance();
|
|
105
102
|
var clientVersion = socketManager.getDocumentVersion();
|
|
@@ -108,7 +105,7 @@ var SocketClient = /*#__PURE__*/_createClass(function SocketClient(config) {
|
|
|
108
105
|
version: clientVersion
|
|
109
106
|
}, function (result) {
|
|
110
107
|
if (result.success) {
|
|
111
|
-
socketManager.
|
|
108
|
+
socketManager.onGetRecentOperations(result);
|
|
112
109
|
}
|
|
113
110
|
});
|
|
114
111
|
};
|
|
@@ -139,7 +136,7 @@ var SocketClient = /*#__PURE__*/_createClass(function SocketClient(config) {
|
|
|
139
136
|
this.socket.on('connect_error', this.onConnectError);
|
|
140
137
|
this.socket.on('join-room', this.onJoinRoom);
|
|
141
138
|
this.socket.on('leave-room', this.onLeaveRoom);
|
|
142
|
-
this.socket.on('update-document', this.
|
|
139
|
+
this.socket.on('update-document', this.onReceiveRemoteOperations);
|
|
143
140
|
this.socket.on('update-cursor', this.receiveCursorLocation);
|
|
144
141
|
this.socket.io.on('reconnect', this.onReconnect);
|
|
145
142
|
this.socket.io.on('reconnect_attempt', this.onReconnectAttempt);
|
|
@@ -6,6 +6,18 @@ import { syncRemoteOperations, reExecRevertOperationList, revertOperationList, s
|
|
|
6
6
|
import SocketClient from './socket-client';
|
|
7
7
|
import debug from '../utils/debug';
|
|
8
8
|
import { deleteCursor } from '../cursor/helper';
|
|
9
|
+
|
|
10
|
+
// idle --> sending --> conflict --> idle
|
|
11
|
+
// --> conflict --> idle
|
|
12
|
+
// --> disconnect --> conflict --> idle
|
|
13
|
+
// --> idle
|
|
14
|
+
var STATE = {
|
|
15
|
+
IDLE: 'idle',
|
|
16
|
+
SENDING: 'sending',
|
|
17
|
+
CONFLICT: 'conflict',
|
|
18
|
+
DISCONNECT: 'disconnect',
|
|
19
|
+
NEED_RELOAD: 'need_reload'
|
|
20
|
+
};
|
|
9
21
|
var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, document, config) {
|
|
10
22
|
var _this = this;
|
|
11
23
|
_classCallCheck(this, SocketManager);
|
|
@@ -13,7 +25,7 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
13
25
|
var version = _this.document.version;
|
|
14
26
|
return version;
|
|
15
27
|
};
|
|
16
|
-
this.
|
|
28
|
+
this.onReceiveLocalOperations = function (operations) {
|
|
17
29
|
_this.pendingOperationList.push(operations);
|
|
18
30
|
if (_this.pendingOperationList.length > 5) {
|
|
19
31
|
_this.dispatchConnectState('pending_operations_exceed_limit');
|
|
@@ -21,16 +33,16 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
21
33
|
_this.sendOperations();
|
|
22
34
|
};
|
|
23
35
|
this.sendOperations = function () {
|
|
24
|
-
if (_this.
|
|
25
|
-
_this.
|
|
36
|
+
if (_this.state !== STATE.IDLE) return;
|
|
37
|
+
_this.state = STATE.SENDING;
|
|
26
38
|
_this.sendNextOperations();
|
|
27
39
|
};
|
|
28
40
|
this.sendNextOperations = function () {
|
|
41
|
+
if (_this.state !== STATE.SENDING) return;
|
|
29
42
|
if (_this.pendingOperationList.length === 0) {
|
|
30
|
-
_this.
|
|
43
|
+
_this.state = STATE.IDLE;
|
|
31
44
|
return;
|
|
32
45
|
}
|
|
33
|
-
if (_this._sendingOperations || _this.disconnect) return;
|
|
34
46
|
_this.dispatchConnectState('is-saving');
|
|
35
47
|
var version = _this.document.version;
|
|
36
48
|
var operations = _this.pendingOperationList.shift();
|
|
@@ -40,166 +52,101 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
40
52
|
};
|
|
41
53
|
this.sendOperationsCallback = function (result) {
|
|
42
54
|
if (result && result.success) {
|
|
43
|
-
_this._sendingOperations = null;
|
|
44
55
|
var serverVersion = result.version;
|
|
45
56
|
_this.document['version'] = serverVersion;
|
|
46
57
|
var lastSavedAt = new Date().getTime();
|
|
47
58
|
_this.dispatchConnectState('saved', lastSavedAt);
|
|
59
|
+
|
|
60
|
+
// send next operations
|
|
61
|
+
_this._sendingOperations = null;
|
|
48
62
|
_this.sendNextOperations();
|
|
49
63
|
return;
|
|
50
64
|
}
|
|
51
65
|
|
|
52
66
|
// Operations are execute failure
|
|
53
67
|
var error_type = result.error_type;
|
|
54
|
-
if (error_type === '
|
|
55
|
-
|
|
56
|
-
//
|
|
57
|
-
_this.pendingOperationList.unshift(dupSendingOperations);
|
|
58
|
-
var lose_operations = result.lose_operations;
|
|
59
|
-
_this.execLoseOperations(lose_operations);
|
|
60
|
-
} else if (error_type === 'document_content_load_failed') {
|
|
61
|
-
_this._sendingOperations = null;
|
|
62
|
-
// After a short-term reconnection, the content of the document fails to load
|
|
68
|
+
if (error_type === 'load_document_content_error' || error_type === 'save_operations_to_database_error') {
|
|
69
|
+
// load_document_content_error: After a short-term reconnection, the content of the document fails to load
|
|
70
|
+
// save_operation_to_database_error: Save operation to database error
|
|
63
71
|
_this.dispatchConnectState(error_type);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
_this.
|
|
67
|
-
} else if (error_type === 'operation_exec_error') {
|
|
68
|
-
var _dupSendingOperations = _toConsumableArray(_this._sendingOperations);
|
|
72
|
+
|
|
73
|
+
// reset sending control
|
|
74
|
+
_this.state = STATE.NEED_RELOAD;
|
|
69
75
|
_this._sendingOperations = null;
|
|
76
|
+
} else if (error_type === 'version_behind_server') {
|
|
77
|
+
// Put the failed operation into the pending list and re-execute it
|
|
78
|
+
_this.pendingOperationList.unshift(_toConsumableArray(_this._sendingOperations));
|
|
79
|
+
_this.state = STATE.CONFLICT;
|
|
80
|
+
var lose_operations = result.lose_operations;
|
|
81
|
+
_this.resolveConflicting(lose_operations);
|
|
82
|
+
} else if (error_type === 'execute_client_operations_error') {
|
|
70
83
|
_this.editor.isRemote = true;
|
|
71
|
-
|
|
84
|
+
var dupSendingOperations = _toConsumableArray(_this._sendingOperations);
|
|
85
|
+
revertOperationList(_this.editor, [dupSendingOperations]);
|
|
72
86
|
|
|
73
|
-
//
|
|
87
|
+
// Update the save time after revert
|
|
88
|
+
var _lastSavedAt = new Date().getTime();
|
|
89
|
+
_this.dispatchConnectState('saved', _lastSavedAt);
|
|
90
|
+
|
|
91
|
+
// Set isRemote to false must be in Promise.resolve function, make sure the modification of isRemote is later than the onChange event
|
|
74
92
|
Promise.resolve().then(function (_) {
|
|
75
93
|
_this.editor.isRemote = false;
|
|
76
94
|
_this.dispatchConnectState(error_type);
|
|
95
|
+
|
|
96
|
+
// send next operations
|
|
97
|
+
_this._sendingOperations = null;
|
|
77
98
|
_this.sendNextOperations();
|
|
78
99
|
});
|
|
79
100
|
}
|
|
80
101
|
};
|
|
81
|
-
this.
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return prev.version - next.version;
|
|
93
|
-
});
|
|
94
|
-
debug('Editor isRemote is true: %s', _this.editor.isRemote);
|
|
95
|
-
while (loseOperations.length > 0) {
|
|
96
|
-
var operationParams = loseOperations.shift();
|
|
97
|
-
// 2. execute operations
|
|
98
|
-
var operations = operationParams.operations,
|
|
99
|
-
serverVersion = operationParams.version;
|
|
100
|
-
// 2.1 Update content & version
|
|
102
|
+
this.onReceiveRemoteOperations = function (params) {
|
|
103
|
+
// if this.disconnect is true, Then the message sent by the remote end cannot be received
|
|
104
|
+
if (_this.state !== STATE.IDLE) return;
|
|
105
|
+
var serverVersion = params.version;
|
|
106
|
+
var clientVersion = _this.document.version;
|
|
107
|
+
if (serverVersion === clientVersion + 1) {
|
|
108
|
+
// update execute remote operations flag
|
|
109
|
+
_this.editor.isRemote = true;
|
|
110
|
+
debug('Editor isRemote is true: %s', _this.editor.isRemote);
|
|
111
|
+
var operations = params.operations;
|
|
112
|
+
// Update content & version
|
|
101
113
|
debug('execute remote operations: %O', operations);
|
|
102
|
-
|
|
114
|
+
try {
|
|
115
|
+
syncRemoteOperations(_this.editor, operations);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
_this.state = STATE.CONFLICT;
|
|
118
|
+
_this.dispatchConnectState('sync_server_operations_error');
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
103
121
|
|
|
104
|
-
//
|
|
122
|
+
// Update document
|
|
105
123
|
_this.document.version = serverVersion;
|
|
106
124
|
_this.document.children = _this.editor.children;
|
|
125
|
+
Promise.resolve().then(function () {
|
|
126
|
+
_this.editor.isRemote = false;
|
|
127
|
+
_this.revertOperationList = [];
|
|
128
|
+
});
|
|
129
|
+
} else {
|
|
130
|
+
// isConflict
|
|
131
|
+
_this.onConflictHappen();
|
|
107
132
|
}
|
|
108
|
-
|
|
109
|
-
// Re-execute undone operations after isRemote is set to false
|
|
110
|
-
// Need resend this operations to server
|
|
111
|
-
|
|
112
|
-
// reset execute remote operations flag
|
|
113
|
-
_this.editor.isRemote = false;
|
|
114
|
-
_this.isSending = false;
|
|
115
|
-
_this._sendingOperations = null;
|
|
116
|
-
|
|
117
|
-
// 3. Execute pending operations
|
|
118
|
-
// 3.1 Re-execute operations
|
|
119
|
-
debug('Editor isRemote is false: %s', _this.editor.isRemote);
|
|
120
|
-
debug('Re-execute pending operations, %O', _this.revertOperationList);
|
|
121
|
-
reExecRevertOperationList(_this.editor, _this.revertOperationList);
|
|
122
|
-
|
|
123
|
-
// 3.2 Clear revert operationList
|
|
124
|
-
_this.revertOperationList = [];
|
|
125
133
|
};
|
|
126
|
-
this.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
});
|
|
133
|
-
var clientVersion = _this.document.version;
|
|
134
|
-
_this.remoteOperationsList = _this.remoteOperationsList.filter(function (item) {
|
|
135
|
-
return item.version > clientVersion;
|
|
136
|
-
});
|
|
134
|
+
this.onReconnect = function (result) {
|
|
135
|
+
var serverVersion = result.version;
|
|
136
|
+
var clientVersion = _this.getDocumentVersion();
|
|
137
|
+
// The client version is inconsistent with the server version, and the latest operations performed by the server need to be loaded
|
|
138
|
+
if (serverVersion !== clientVersion) {
|
|
139
|
+
_this.onConflictHappen();
|
|
137
140
|
}
|
|
138
|
-
if (_this.isExecRemoteOperations || _this._sendingOperations) return;
|
|
139
141
|
|
|
140
|
-
//
|
|
141
|
-
_this.
|
|
142
|
-
_this.editor.isRemote = true;
|
|
143
|
-
_this.execRemoteOperations();
|
|
142
|
+
// The version consistency indicates that there is no conflict and no processing is required
|
|
143
|
+
_this.state = STATE.IDLE;
|
|
144
144
|
};
|
|
145
|
-
this.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
var serverVersion = params.version;
|
|
149
|
-
var clientVersion = _this.document.version;
|
|
150
|
-
if (serverVersion === clientVersion + 1) {
|
|
151
|
-
// When performing remote operations, the revert operation is only required for the first time
|
|
152
|
-
if (_this.revertOperationList.length === 0) {
|
|
153
|
-
// 1. Revert operations
|
|
154
|
-
// 1.1 record reverted operationList & clear pendingOperationList
|
|
155
|
-
_this.revertOperationList = _this.pendingOperationList.slice();
|
|
156
|
-
_this.pendingOperationList = [];
|
|
157
|
-
|
|
158
|
-
// 1.2 Revert operationList
|
|
159
|
-
debug('revert locale operations: %O', _this.revertOperationList);
|
|
160
|
-
revertOperationList(_this.editor, _this.revertOperationList);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// 2. execute operations
|
|
164
|
-
var operations = params.operations;
|
|
165
|
-
// 2.1 Update content & version
|
|
166
|
-
debug('execute remote operations: %O', operations);
|
|
167
|
-
syncRemoteOperations(_this.editor, operations);
|
|
168
|
-
|
|
169
|
-
// 2.2 Update document
|
|
170
|
-
_this.document.version = serverVersion;
|
|
171
|
-
_this.document.children = _this.editor.children;
|
|
172
|
-
|
|
173
|
-
// Execute next operations
|
|
174
|
-
if (_this.remoteOperationsList.length > 0) {
|
|
175
|
-
_this.execRemoteOperations();
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Re-execute undone operations after isRemote is set to false
|
|
180
|
-
// Need resend this operations to server
|
|
181
|
-
Promise.resolve().then(function (_) {
|
|
182
|
-
// reset execute remote operations flag
|
|
183
|
-
_this.isExecRemoteOperations = false;
|
|
184
|
-
_this.editor.isRemote = false;
|
|
185
|
-
|
|
186
|
-
// 3. Execute pending operations
|
|
187
|
-
// 3.1 Re-execute operations
|
|
188
|
-
debug('Editor isRemote is false: %s', _this.editor.isRemote);
|
|
189
|
-
debug('Re-execute pending operations, %O', _this.revertOperationList);
|
|
190
|
-
reExecRevertOperationList(_this.editor, _this.revertOperationList);
|
|
191
|
-
|
|
192
|
-
// 3.2 Clear revert operationList
|
|
193
|
-
_this.revertOperationList = [];
|
|
194
|
-
});
|
|
195
|
-
} else {
|
|
196
|
-
// conflict:
|
|
197
|
-
// remote operations is not empty, waiting until remote operations all executed
|
|
198
|
-
debug('remote operations is not empty, and local version is not match remote version.');
|
|
199
|
-
}
|
|
200
|
-
}
|
|
145
|
+
this.onConflictHappen = function () {
|
|
146
|
+
_this.state = STATE.CONFLICT;
|
|
147
|
+
_this.socketClient.getRecentOperations();
|
|
201
148
|
};
|
|
202
|
-
this.
|
|
149
|
+
this.onGetRecentOperations = function (result) {
|
|
203
150
|
var mode = result.mode,
|
|
204
151
|
content = result.content;
|
|
205
152
|
// sync document
|
|
@@ -213,6 +160,8 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
213
160
|
_this.editor.isRemote = true;
|
|
214
161
|
_this.editor.onChange();
|
|
215
162
|
_this.editor.isRemote = false;
|
|
163
|
+
_this.state = STATE.IDLE;
|
|
164
|
+
_this._sendingOperations = null;
|
|
216
165
|
|
|
217
166
|
// 2. exec client operationList
|
|
218
167
|
var pendingOperationList = _this.pendingOperationList.slice();
|
|
@@ -224,14 +173,73 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
224
173
|
return;
|
|
225
174
|
}
|
|
226
175
|
|
|
227
|
-
// sync operations
|
|
176
|
+
// mode os operations: sync operations
|
|
228
177
|
// content is [{version, operations}, {version, operations}, ...]
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
178
|
+
var loseOperations = content;
|
|
179
|
+
_this.resolveConflicting(loseOperations);
|
|
180
|
+
};
|
|
181
|
+
this.resolveConflicting = function (loseOperations) {
|
|
233
182
|
_this.editor.isRemote = true;
|
|
234
|
-
_this.
|
|
183
|
+
debug('Editor isRemote is true: %s', _this.editor.isRemote);
|
|
184
|
+
if (_this.pendingOperationList.length !== 0) {
|
|
185
|
+
// 1. Revert operations
|
|
186
|
+
// 1.1 record reverted operationList & clear pendingOperationList
|
|
187
|
+
_this.revertOperationList = _this.pendingOperationList.slice();
|
|
188
|
+
_this.pendingOperationList = [];
|
|
189
|
+
|
|
190
|
+
// 1.2 Revert operationList
|
|
191
|
+
debug('revert locale operations: %O', _this.revertOperationList);
|
|
192
|
+
revertOperationList(_this.editor, _this.revertOperationList);
|
|
193
|
+
}
|
|
194
|
+
loseOperations = loseOperations.sort(function (prev, next) {
|
|
195
|
+
return prev.version - next.version;
|
|
196
|
+
});
|
|
197
|
+
debug('lose operations length: %s', loseOperations.length);
|
|
198
|
+
while (loseOperations.length > 0) {
|
|
199
|
+
var operationParams = loseOperations.shift();
|
|
200
|
+
// 2. execute operations
|
|
201
|
+
var operations = operationParams.operations,
|
|
202
|
+
serverVersion = operationParams.version;
|
|
203
|
+
// 2.1 Update content & version
|
|
204
|
+
debug('execute lose operations: %O', operations);
|
|
205
|
+
try {
|
|
206
|
+
syncRemoteOperations(_this.editor, operations);
|
|
207
|
+
} catch (error) {
|
|
208
|
+
_this.state = STATE.CONFLICT;
|
|
209
|
+
_this.dispatchConnectState('sync_server_operations_error');
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 2.2 Update document
|
|
214
|
+
_this.document.version = serverVersion;
|
|
215
|
+
_this.document.children = _this.editor.children;
|
|
216
|
+
}
|
|
217
|
+
if (_this.revertOperationList.length === 0) {
|
|
218
|
+
Promise.resolve().then(function () {
|
|
219
|
+
_this.editor.isRemote = false;
|
|
220
|
+
_this.state = STATE.IDLE;
|
|
221
|
+
_this._sendingOperations = null;
|
|
222
|
+
_this.revertOperationList = [];
|
|
223
|
+
});
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Set isRemote to false must be in Promise.resolve function, make sure the modification of isRemote is later than the onChange event
|
|
228
|
+
Promise.resolve().then(function () {
|
|
229
|
+
// reset execute remote operations flag
|
|
230
|
+
_this.editor.isRemote = false;
|
|
231
|
+
_this.state = STATE.IDLE;
|
|
232
|
+
_this._sendingOperations = null;
|
|
233
|
+
|
|
234
|
+
// 3. Execute pending operations
|
|
235
|
+
// 3.1 Re-execute operations
|
|
236
|
+
debug('Editor isRemote is false: %s', _this.editor.isRemote);
|
|
237
|
+
debug('Re-execute pending operations, %O', _this.revertOperationList);
|
|
238
|
+
reExecRevertOperationList(_this.editor, _this.revertOperationList);
|
|
239
|
+
|
|
240
|
+
// 3.2 Clear revert operationList
|
|
241
|
+
_this.revertOperationList = [];
|
|
242
|
+
});
|
|
235
243
|
};
|
|
236
244
|
this.sendCursorLocation = function (location) {
|
|
237
245
|
_this.socketClient.sendCursorLocation(location);
|
|
@@ -253,16 +261,12 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
253
261
|
_this.pendingOperationList.unshift(_this._sendingOperations.slice());
|
|
254
262
|
_this._sendingOperations = null;
|
|
255
263
|
}
|
|
256
|
-
_this.
|
|
257
|
-
_this.disconnect = true;
|
|
264
|
+
_this.state = STATE.DISCONNECT;
|
|
258
265
|
|
|
259
266
|
// Update saved state
|
|
260
267
|
var lastSavedAt = new Date().getTime();
|
|
261
268
|
_this.dispatchConnectState('saved', lastSavedAt);
|
|
262
269
|
}
|
|
263
|
-
if (type === 'reconnect') {
|
|
264
|
-
_this.disconnect = false;
|
|
265
|
-
}
|
|
266
270
|
_this.eventBus.dispatch(type, message);
|
|
267
271
|
};
|
|
268
272
|
this.closeSocketConnect = function () {
|
|
@@ -271,11 +275,11 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
271
275
|
this.editor = editor;
|
|
272
276
|
this.document = document;
|
|
273
277
|
this.socketClient = new SocketClient(config);
|
|
274
|
-
this.isSending = false;
|
|
275
278
|
this.pendingOperationList = []; // Two-dimensional arrays: [operations, operations, ...]
|
|
276
279
|
this.remoteOperationsList = []; // Same with pending operations
|
|
277
280
|
this.revertOperationList = [];
|
|
278
281
|
this.eventBus = EventBus.getInstance();
|
|
282
|
+
this.state = STATE.IDLE;
|
|
279
283
|
});
|
|
280
284
|
SocketManager.getInstance = function (editor, document, socketConfig) {
|
|
281
285
|
if (SocketManager.instance) {
|
|
@@ -30,7 +30,7 @@ var withSocketIO = function withSocketIO(editor, options) {
|
|
|
30
30
|
var updateOperations = operations.filter(function (operation) {
|
|
31
31
|
return operation.type !== 'set_selection';
|
|
32
32
|
});
|
|
33
|
-
_socketManager.
|
|
33
|
+
_socketManager.onReceiveLocalOperations(updateOperations);
|
|
34
34
|
}
|
|
35
35
|
_socketManager.sendCursorLocation(editor.selection);
|
|
36
36
|
}
|
|
@@ -18,35 +18,34 @@ var TipMessage = /*#__PURE__*/function (_React$Component) {
|
|
|
18
18
|
_this.onOperationExecuteError = function () {
|
|
19
19
|
var t = _this.props.t;
|
|
20
20
|
var message = t('Failed_to_execute_operation_on_server');
|
|
21
|
-
toaster.danger(message, {
|
|
22
|
-
hasCloseButton: true,
|
|
23
|
-
duration: null
|
|
24
|
-
});
|
|
25
|
-
};
|
|
26
|
-
_this.onPendingOpExceedLimit = function () {
|
|
27
|
-
var t = _this.props.t;
|
|
28
|
-
toaster.closeAll();
|
|
29
|
-
var message = t('Pending_operations_exceed_limit');
|
|
30
21
|
toaster.warning(message, {
|
|
31
|
-
|
|
22
|
+
hasCloseButton: true
|
|
32
23
|
});
|
|
33
24
|
};
|
|
34
|
-
_this.
|
|
25
|
+
_this.onSyncServerOperationError = function () {
|
|
35
26
|
var t = _this.props.t;
|
|
36
|
-
var message = t('
|
|
27
|
+
var message = t('Failed_to_sync_with_server_operations');
|
|
37
28
|
toaster.danger(message, {
|
|
38
|
-
hasCloseButton:
|
|
29
|
+
hasCloseButton: false,
|
|
39
30
|
duration: null
|
|
40
31
|
});
|
|
41
32
|
};
|
|
42
|
-
_this.
|
|
33
|
+
_this.onInternalServerExecError = function () {
|
|
43
34
|
var t = _this.props.t;
|
|
44
|
-
var message = t('
|
|
35
|
+
var message = t('Internal_server_exec_operations_error');
|
|
45
36
|
toaster.danger(message, {
|
|
46
37
|
hasCloseButton: false,
|
|
47
38
|
duration: null
|
|
48
39
|
});
|
|
49
40
|
};
|
|
41
|
+
_this.onPendingOpExceedLimit = function () {
|
|
42
|
+
var t = _this.props.t;
|
|
43
|
+
toaster.closeAll();
|
|
44
|
+
var message = t('Pending_operations_exceed_limit');
|
|
45
|
+
toaster.warning(message, {
|
|
46
|
+
duration: 5
|
|
47
|
+
});
|
|
48
|
+
};
|
|
50
49
|
_this.onDisconnect = function () {
|
|
51
50
|
var _this$props = _this.props,
|
|
52
51
|
t = _this$props.t,
|
|
@@ -142,18 +141,28 @@ var TipMessage = /*#__PURE__*/function (_React$Component) {
|
|
|
142
141
|
this.unsubscribeReconnectErrorEvent = eventBus.subscribe('reconnect_error', this.onReconnectError);
|
|
143
142
|
this.unsubscribeReconnectEvent = eventBus.subscribe('reconnect', this.onReconnect);
|
|
144
143
|
|
|
145
|
-
//
|
|
146
|
-
this.unsubscribeOpExecError = eventBus.subscribe('
|
|
144
|
+
// server return error
|
|
145
|
+
this.unsubscribeOpExecError = eventBus.subscribe('execute_client_operations_error', this.onOperationExecuteError);
|
|
146
|
+
this.unsubscribeSyncServerOpError = eventBus.subscribe('sync_server_operations_error', this.onSyncServerOperationError);
|
|
147
|
+
this.unsubscribeDocumentLoadError = eventBus.subscribe('load_document_content_error', this.onInternalServerExecError);
|
|
148
|
+
this.unsubscribeOperationsSaveError = eventBus.subscribe('save_operations_to_database_error', this.onInternalServerExecError);
|
|
149
|
+
|
|
150
|
+
// local error
|
|
147
151
|
this.unsubscribePendingOpExceedLimit = eventBus.subscribe('pending_operations_exceed_limit', this.onPendingOpExceedLimit);
|
|
148
|
-
this.unsubscribeDocumentLoadError = eventBus.subscribe('document_content_load_failed', this.onDocumentLoadError);
|
|
149
|
-
this.unsubscribeOperationsSaveError = eventBus.subscribe('Internal_server_error', this.onOperationsSaveError);
|
|
150
152
|
}
|
|
151
153
|
}, {
|
|
152
154
|
key: "componentWillUnmount",
|
|
153
155
|
value: function componentWillUnmount() {
|
|
154
156
|
this.unsubscribeSavingEvent();
|
|
155
157
|
this.unsubscribeSavedEvent();
|
|
158
|
+
this.unsubscribeDisconnectEvent();
|
|
159
|
+
this.unsubscribeReconnectErrorEvent();
|
|
160
|
+
this.unsubscribeReconnectEvent();
|
|
161
|
+
this.unsubscribeOpExecError();
|
|
162
|
+
this.unsubscribeSyncServerOpError();
|
|
163
|
+
this.unsubscribePendingOpExceedLimit();
|
|
156
164
|
this.unsubscribeDocumentLoadError();
|
|
165
|
+
this.unsubscribeOperationsSaveError();
|
|
157
166
|
clearTimeout(this.saveTimer);
|
|
158
167
|
}
|
|
159
168
|
}]);
|
package/package.json
CHANGED
|
@@ -273,7 +273,7 @@
|
|
|
273
273
|
"Revision": "Revision",
|
|
274
274
|
"Error": "Error",
|
|
275
275
|
"Start_revise": "Start revise",
|
|
276
|
-
"Failed_to_execute_operation_on_server": "Failed to execute operation on server",
|
|
276
|
+
"Failed_to_execute_operation_on_server": "Failed to execute operation on server, the current operation has been withdrawn",
|
|
277
277
|
"Start_revise_tip": "Create a temporary document and modify on it, merge it back after reviewing changes",
|
|
278
278
|
"Load_doc_content_error": "Load doc content error",
|
|
279
279
|
"Sdoc_format_invalid": "The content of the document does not conform to the sdoc specification",
|
|
@@ -341,7 +341,6 @@
|
|
|
341
341
|
"Font": "Font",
|
|
342
342
|
"All_fonts": "All fonts",
|
|
343
343
|
"Default_font": "Default font",
|
|
344
|
-
"Document_content_load_failed": "Document content failed to load, please refresh the page to try again",
|
|
345
344
|
"Pending_operations_exceed_limit": "There are multiple operations not synced to the server. Please check your network.",
|
|
346
345
|
"Recently_saved": "Recently saved",
|
|
347
346
|
"Sdoc_document" : "Sdoc document",
|
|
@@ -350,5 +349,6 @@
|
|
|
350
349
|
"Card": "Card",
|
|
351
350
|
"Select_sdoc_document": "Select sdoc document",
|
|
352
351
|
"Local_file": "Local file",
|
|
353
|
-
"
|
|
352
|
+
"Internal_server_exec_operations_error": "An exception occurred on the server, please refresh the page and try again",
|
|
353
|
+
"Failed_to_sync_with_server_operations": "Synchronization with the server failed, please refresh the page"
|
|
354
354
|
}
|
|
@@ -273,7 +273,7 @@
|
|
|
273
273
|
"Revision": "修订稿",
|
|
274
274
|
"Error": "错误",
|
|
275
275
|
"Start_revise": "开始修订",
|
|
276
|
-
"Failed_to_execute_operation_on_server": "
|
|
276
|
+
"Failed_to_execute_operation_on_server": "无法在服务器上执行操作,当前操作已经撤回",
|
|
277
277
|
"Start_revise_tip": "创建一个临时文档并对其进行修订,检查更改后将其合并回来",
|
|
278
278
|
"Load_doc_content_error": "加载文档内容错误",
|
|
279
279
|
"Sdoc_format_invalid": "文档内容不符合 sdoc 规范",
|
|
@@ -343,7 +343,6 @@
|
|
|
343
343
|
"Font": "字体",
|
|
344
344
|
"All_fonts": "所有字体",
|
|
345
345
|
"Default_font": "默认字体",
|
|
346
|
-
"Document_content_load_failed": "文档内容加载失败, 请刷新页面重新访问",
|
|
347
346
|
"Pending_operations_exceed_limit": "有多个操作未同步到服务器。请检查你的网络。",
|
|
348
347
|
"Recently_saved": "最近保存",
|
|
349
348
|
"Sdoc_document" : "sdoc 文档",
|
|
@@ -352,5 +351,6 @@
|
|
|
352
351
|
"Card": "卡片",
|
|
353
352
|
"Select_sdoc_document": "选择sdoc文档",
|
|
354
353
|
"Local_file": "本地文件",
|
|
355
|
-
"
|
|
354
|
+
"Internal_server_exec_operations_error": "在服务器执行操作异常,请刷新页面后重试",
|
|
355
|
+
"Failed_to_sync_with_server_operations": "与服务器同步操作失败,请刷新页面"
|
|
356
356
|
}
|