mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-02-01 03:12:42 +01:00
collab_client: Promisify deferred actions
This commit is contained in:
parent
5814b76aa4
commit
966ba54874
1 changed files with 28 additions and 23 deletions
|
@ -31,6 +31,18 @@ const browser = require('./vendors/browser');
|
||||||
let pad = undefined;
|
let pad = undefined;
|
||||||
const getSocket = () => pad && pad.socket;
|
const getSocket = () => pad && pad.socket;
|
||||||
|
|
||||||
|
// Gate is a normal Promise that resolves when its open() method is called.
|
||||||
|
class Gate extends Promise {
|
||||||
|
constructor(executor = null) {
|
||||||
|
let open;
|
||||||
|
super((resolve, reject) => {
|
||||||
|
open = resolve;
|
||||||
|
if (executor != null) executor(resolve, reject);
|
||||||
|
});
|
||||||
|
this.open = open;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Call this when the document is ready, and a new Ace2Editor() has been created and inited.
|
/** Call this when the document is ready, and a new Ace2Editor() has been created and inited.
|
||||||
ACE's ready callback does not need to have fired yet.
|
ACE's ready callback does not need to have fired yet.
|
||||||
"serverVars" are from calling doc.getCollabClientVars() on the server. */
|
"serverVars" are from calling doc.getCollabClientVars() on the server. */
|
||||||
|
@ -63,6 +75,12 @@ const getCollabClient = (ace2editor, serverVars, initialUserInfo, options, _pad)
|
||||||
onConnectionTrouble: () => {},
|
onConnectionTrouble: () => {},
|
||||||
onServerMessage: () => {},
|
onServerMessage: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We need to present a working interface even before the socket is connected for the first time.
|
||||||
|
// Use a Gate to block actions until connected. Once connected, the Gate is opened which causes
|
||||||
|
// post-connect actions to start running.
|
||||||
|
let connectedGate = new Gate();
|
||||||
|
|
||||||
if (browser.firefox) {
|
if (browser.firefox) {
|
||||||
// Prevent "escape" from taking effect and canceling a comet connection;
|
// Prevent "escape" from taking effect and canceling a comet connection;
|
||||||
// doesn't work if focus is on an iframe.
|
// doesn't work if focus is on an iframe.
|
||||||
|
@ -302,7 +320,8 @@ const getCollabClient = (ace2editor, serverVars, initialUserInfo, options, _pad)
|
||||||
hooks.callAll(`handleClientMessage_${msg.type}`, {payload: msg.payload});
|
hooks.callAll(`handleClientMessage_${msg.type}`, {payload: msg.payload});
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateUserInfo = (userInfo) => {
|
const updateUserInfo = async (userInfo) => {
|
||||||
|
await connectedGate;
|
||||||
userInfo.userId = userId;
|
userInfo.userId = userId;
|
||||||
userSet[userId] = userInfo;
|
userSet[userId] = userInfo;
|
||||||
tellAceActiveAuthorInfo(userInfo);
|
tellAceActiveAuthorInfo(userInfo);
|
||||||
|
@ -352,6 +371,12 @@ const getCollabClient = (ace2editor, serverVars, initialUserInfo, options, _pad)
|
||||||
|
|
||||||
const setChannelState = (newChannelState, moreInfo) => {
|
const setChannelState = (newChannelState, moreInfo) => {
|
||||||
if (newChannelState === channelState) return;
|
if (newChannelState === channelState) return;
|
||||||
|
if (channelState === 'CONNECTED') {
|
||||||
|
// The old channel state is CONNECTED, which means we have just disconnected. Re-initialize
|
||||||
|
// connectedGate so that actions are deferred until connected again. Do this before calling
|
||||||
|
// onChannelStateChange() so that the event handler can create deferred actions if desired.
|
||||||
|
connectedGate = new Gate();
|
||||||
|
}
|
||||||
channelState = newChannelState;
|
channelState = newChannelState;
|
||||||
callbacks.onChannelStateChange(channelState, moreInfo);
|
callbacks.onChannelStateChange(channelState, moreInfo);
|
||||||
switch (channelState) {
|
switch (channelState) {
|
||||||
|
@ -360,7 +385,7 @@ const getCollabClient = (ace2editor, serverVars, initialUserInfo, options, _pad)
|
||||||
startConnectTime = Date.now();
|
startConnectTime = Date.now();
|
||||||
break;
|
break;
|
||||||
case 'CONNECTED':
|
case 'CONNECTED':
|
||||||
doDeferredActions();
|
connectedGate.open();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -373,26 +398,6 @@ const getCollabClient = (ace2editor, serverVars, initialUserInfo, options, _pad)
|
||||||
return array;
|
return array;
|
||||||
};
|
};
|
||||||
|
|
||||||
// We need to present a working interface even before the socket
|
|
||||||
// is connected for the first time.
|
|
||||||
let deferredActions = [];
|
|
||||||
|
|
||||||
const defer = (func) => function (...args) {
|
|
||||||
const action = () => {
|
|
||||||
func.call(this, ...args);
|
|
||||||
};
|
|
||||||
if (channelState !== 'CONNECTED') {
|
|
||||||
deferredActions.push(action);
|
|
||||||
} else {
|
|
||||||
action();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const doDeferredActions = () => {
|
|
||||||
for (const action of deferredActions) action();
|
|
||||||
deferredActions = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendClientMessage = (msg) => {
|
const sendClientMessage = (msg) => {
|
||||||
sendMessage(
|
sendMessage(
|
||||||
{
|
{
|
||||||
|
@ -470,7 +475,7 @@ const getCollabClient = (ace2editor, serverVars, initialUserInfo, options, _pad)
|
||||||
setOnConnectionTrouble: (cb) => {
|
setOnConnectionTrouble: (cb) => {
|
||||||
callbacks.onConnectionTrouble = cb;
|
callbacks.onConnectionTrouble = cb;
|
||||||
},
|
},
|
||||||
updateUserInfo: defer(updateUserInfo),
|
updateUserInfo,
|
||||||
handleMessageFromServer,
|
handleMessageFromServer,
|
||||||
getConnectedUsers,
|
getConnectedUsers,
|
||||||
sendClientMessage,
|
sendClientMessage,
|
||||||
|
|
Loading…
Reference in a new issue