mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-31 19:02:59 +01:00
pad: Simplify reload after .etherpad
import
The old "switch to pad" logic looked buggy, and it complicates pad initialization. Forcing a refresh after importing an `.etherpad` file isn't much of a UX downgrade.
This commit is contained in:
parent
e974622561
commit
5cbbcbcee6
6 changed files with 10 additions and 83 deletions
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
### Notable enhancements
|
### Notable enhancements
|
||||||
|
|
||||||
|
* Simplified pad reload after importing an `.etherpad` file.
|
||||||
* For plugin authors:
|
* For plugin authors:
|
||||||
* `clientVars` was added to the context for the `postAceInit` client-side
|
* `clientVars` was added to the context for the `postAceInit` client-side
|
||||||
hook. Plugins should use this instead of the `clientVars` global variable.
|
hook. Plugins should use this instead of the `clientVars` global variable.
|
||||||
|
|
|
@ -579,9 +579,9 @@ Things in context:
|
||||||
This hook allows plugins to grant temporary write access to a pad. It is called
|
This hook allows plugins to grant temporary write access to a pad. It is called
|
||||||
for each incoming message from a client. If write access is granted, it applies
|
for each incoming message from a client. If write access is granted, it applies
|
||||||
to the current message and all future messages from the same socket.io
|
to the current message and all future messages from the same socket.io
|
||||||
connection until the next `CLIENT_READY` or `SWITCH_TO_PAD` message. Read-only
|
connection until the next `CLIENT_READY` message. Read-only access is reset
|
||||||
access is reset **after** each `CLIENT_READY` or `SWITCH_TO_PAD` message, so
|
**after** each `CLIENT_READY` message, so granting write access has no effect
|
||||||
granting write access has no effect for those message types.
|
for those message types.
|
||||||
|
|
||||||
The handleMessageSecurity function must return a Promise. If the Promise
|
The handleMessageSecurity function must return a Promise. If the Promise
|
||||||
resolves to `true`, write access is granted as described above. Returning
|
resolves to `true`, write access is granted as described above. Returning
|
||||||
|
|
|
@ -235,8 +235,8 @@ const doImport = async (req, res, padId) => {
|
||||||
pad = await padManager.getPad(padId);
|
pad = await padManager.getPad(padId);
|
||||||
padManager.unloadPad(padId);
|
padManager.unloadPad(padId);
|
||||||
|
|
||||||
// direct Database Access means a pad user should perform a switchToPad
|
// Direct database access means a pad user should reload the pad and not attempt to receive
|
||||||
// and not attempt to receive updated pad data
|
// updated pad data.
|
||||||
if (directDatabaseAccess) return true;
|
if (directDatabaseAccess) return true;
|
||||||
|
|
||||||
// tell clients to update
|
// tell clients to update
|
||||||
|
|
|
@ -283,8 +283,6 @@ exports.handleMessage = async (socket, message) => {
|
||||||
} else {
|
} else {
|
||||||
messageLogger.warn(`Dropped message, unknown COLLABROOM Data Type ${message.data.type}`);
|
messageLogger.warn(`Dropped message, unknown COLLABROOM Data Type ${message.data.type}`);
|
||||||
}
|
}
|
||||||
} else if (message.type === 'SWITCH_TO_PAD') {
|
|
||||||
await handleSwitchToPad(socket, message, authorID);
|
|
||||||
} else {
|
} else {
|
||||||
messageLogger.warn(`Dropped message, unknown Message Type ${message.type}`);
|
messageLogger.warn(`Dropped message, unknown Message Type ${message.type}`);
|
||||||
}
|
}
|
||||||
|
@ -806,44 +804,6 @@ const _correctMarkersInPad = (atext, apool) => {
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSwitchToPad = async (socket, message, _authorID) => {
|
|
||||||
const currentSessionInfo = sessioninfos[socket.id];
|
|
||||||
const padId = currentSessionInfo.padId;
|
|
||||||
|
|
||||||
// Check permissions for the new pad.
|
|
||||||
const newPadIds = await readOnlyManager.getIds(message.padId);
|
|
||||||
const {session: {user} = {}} = socket.client.request;
|
|
||||||
const {accessStatus, authorID} = await securityManager.checkAccess(
|
|
||||||
newPadIds.padId, message.sessionID, message.token, user);
|
|
||||||
if (accessStatus !== 'grant') {
|
|
||||||
// Access denied. Send the reason to the user.
|
|
||||||
socket.json.send({accessStatus});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// The same token and session ID were passed to checkAccess in handleMessage, so this second call
|
|
||||||
// to checkAccess should return the same author ID.
|
|
||||||
assert(authorID === _authorID);
|
|
||||||
assert(authorID === currentSessionInfo.author);
|
|
||||||
|
|
||||||
// Check if the connection dropped during the access check.
|
|
||||||
if (sessioninfos[socket.id] !== currentSessionInfo) return;
|
|
||||||
|
|
||||||
// clear the session and leave the room
|
|
||||||
_getRoomSockets(padId).forEach((socket) => {
|
|
||||||
const sinfo = sessioninfos[socket.id];
|
|
||||||
if (sinfo && sinfo.author === currentSessionInfo.author) {
|
|
||||||
// fix user's counter, works on page refresh or if user closes browser window and then rejoins
|
|
||||||
sessioninfos[socket.id] = {};
|
|
||||||
socket.leave(padId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// start up the new pad
|
|
||||||
const newSessionInfo = sessioninfos[socket.id];
|
|
||||||
createSessionInfoAuth(newSessionInfo, message);
|
|
||||||
await handleClientReady(socket, message, authorID);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Creates/replaces the auth object in the given session info.
|
// Creates/replaces the auth object in the given session info.
|
||||||
const createSessionInfoAuth = (sessionInfo, message) => {
|
const createSessionInfoAuth = (sessionInfo, message) => {
|
||||||
// Remember this information since we won't
|
// Remember this information since we won't
|
||||||
|
|
|
@ -48,8 +48,6 @@ const socketio = require('./socketio');
|
||||||
|
|
||||||
const hooks = require('./pluginfw/hooks');
|
const hooks = require('./pluginfw/hooks');
|
||||||
|
|
||||||
let receivedClientVars = false;
|
|
||||||
|
|
||||||
// This array represents all GET-parameters which can be used to change a setting.
|
// This array represents all GET-parameters which can be used to change a setting.
|
||||||
// name: the parameter-name, eg `?noColors=true` => `noColors`
|
// name: the parameter-name, eg `?noColors=true` => `noColors`
|
||||||
// checkVal: the callback is only executed when
|
// checkVal: the callback is only executed when
|
||||||
|
@ -181,8 +179,7 @@ const getUrlVars = () => {
|
||||||
return vars;
|
return vars;
|
||||||
};
|
};
|
||||||
|
|
||||||
const sendClientReady = (isReconnect, messageType) => {
|
const sendClientReady = (isReconnect) => {
|
||||||
messageType = typeof messageType !== 'undefined' ? messageType : 'CLIENT_READY';
|
|
||||||
let padId = document.location.pathname.substring(document.location.pathname.lastIndexOf('/') + 1);
|
let padId = document.location.pathname.substring(document.location.pathname.lastIndexOf('/') + 1);
|
||||||
// unescape neccesary due to Safari and Opera interpretation of spaces
|
// unescape neccesary due to Safari and Opera interpretation of spaces
|
||||||
padId = decodeURIComponent(padId);
|
padId = decodeURIComponent(padId);
|
||||||
|
@ -201,7 +198,7 @@ const sendClientReady = (isReconnect, messageType) => {
|
||||||
|
|
||||||
const msg = {
|
const msg = {
|
||||||
component: 'pad',
|
component: 'pad',
|
||||||
type: messageType,
|
type: 'CLIENT_READY',
|
||||||
padId,
|
padId,
|
||||||
sessionID: Cookies.get('sessionID'),
|
sessionID: Cookies.get('sessionID'),
|
||||||
token,
|
token,
|
||||||
|
@ -218,6 +215,7 @@ const sendClientReady = (isReconnect, messageType) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handshake = () => {
|
const handshake = () => {
|
||||||
|
let receivedClientVars = false;
|
||||||
let padId = document.location.pathname.substring(document.location.pathname.lastIndexOf('/') + 1);
|
let padId = document.location.pathname.substring(document.location.pathname.lastIndexOf('/') + 1);
|
||||||
// unescape neccesary due to Safari and Opera interpretation of spaces
|
// unescape neccesary due to Safari and Opera interpretation of spaces
|
||||||
padId = decodeURIComponent(padId);
|
padId = decodeURIComponent(padId);
|
||||||
|
@ -394,38 +392,6 @@ const pad = {
|
||||||
getUserId: () => pad.myUserInfo.userId,
|
getUserId: () => pad.myUserInfo.userId,
|
||||||
getUserName: () => pad.myUserInfo.name,
|
getUserName: () => pad.myUserInfo.name,
|
||||||
userList: () => paduserlist.users(),
|
userList: () => paduserlist.users(),
|
||||||
switchToPad: (padId) => {
|
|
||||||
let newHref = new RegExp(/.*\/p\/[^/]+/).exec(document.location.pathname) || clientVars.padId;
|
|
||||||
newHref = newHref[0];
|
|
||||||
|
|
||||||
const options = clientVars.padOptions;
|
|
||||||
if (typeof options !== 'undefined' && options != null) {
|
|
||||||
const optionArr = [];
|
|
||||||
$.each(options, (k, v) => {
|
|
||||||
const str = `${k}=${v}`;
|
|
||||||
optionArr.push(str);
|
|
||||||
});
|
|
||||||
const optionStr = optionArr.join('&');
|
|
||||||
|
|
||||||
newHref = `${newHref}?${optionStr}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// destroy old pad from DOM
|
|
||||||
// See https://github.com/ether/etherpad-lite/pull/3915
|
|
||||||
// TODO: Check if Destroying is enough and doesn't leave negative stuff
|
|
||||||
// See ace.js "editor.destroy" for a reference of how it was done before
|
|
||||||
$('#editorcontainer').find('iframe')[0].remove();
|
|
||||||
|
|
||||||
if (window.history && window.history.pushState) {
|
|
||||||
$('#chattext p').remove(); // clear the chat messages
|
|
||||||
window.history.pushState('', '', newHref);
|
|
||||||
receivedClientVars = false;
|
|
||||||
sendClientReady(false, 'SWITCH_TO_PAD');
|
|
||||||
} else {
|
|
||||||
// fallback
|
|
||||||
window.location.href = newHref;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sendClientMessage: (msg) => {
|
sendClientMessage: (msg) => {
|
||||||
pad.collabClient.sendClientMessage(msg);
|
pad.collabClient.sendClientMessage(msg);
|
||||||
},
|
},
|
||||||
|
|
|
@ -67,7 +67,7 @@ const padimpexp = (() => {
|
||||||
importErrorMessage(message);
|
importErrorMessage(message);
|
||||||
} else {
|
} else {
|
||||||
$('#import_export').removeClass('popup-show');
|
$('#import_export').removeClass('popup-show');
|
||||||
if (directDatabaseAccess) pad.switchToPad(clientVars.padId);
|
if (directDatabaseAccess) window.location.reload();
|
||||||
}
|
}
|
||||||
$('#importsubmitinput').removeAttr('disabled').val(html10n.get('pad.impexp.importbutton'));
|
$('#importsubmitinput').removeAttr('disabled').val(html10n.get('pad.impexp.importbutton'));
|
||||||
window.setTimeout(() => $('#importfileinput').removeAttr('disabled'), 0);
|
window.setTimeout(() => $('#importfileinput').removeAttr('disabled'), 0);
|
||||||
|
|
Loading…
Reference in a new issue