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.pull/5252/head
parent
e974622561
commit
5cbbcbcee6
|
@ -34,6 +34,7 @@
|
|||
|
||||
### Notable enhancements
|
||||
|
||||
* Simplified pad reload after importing an `.etherpad` file.
|
||||
* For plugin authors:
|
||||
* `clientVars` was added to the context for the `postAceInit` client-side
|
||||
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
|
||||
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
|
||||
connection until the next `CLIENT_READY` or `SWITCH_TO_PAD` message. Read-only
|
||||
access is reset **after** each `CLIENT_READY` or `SWITCH_TO_PAD` message, so
|
||||
granting write access has no effect for those message types.
|
||||
connection until the next `CLIENT_READY` message. Read-only access is reset
|
||||
**after** each `CLIENT_READY` message, so granting write access has no effect
|
||||
for those message types.
|
||||
|
||||
The handleMessageSecurity function must return a Promise. If the Promise
|
||||
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);
|
||||
padManager.unloadPad(padId);
|
||||
|
||||
// direct Database Access means a pad user should perform a switchToPad
|
||||
// and not attempt to receive updated pad data
|
||||
// Direct database access means a pad user should reload the pad and not attempt to receive
|
||||
// updated pad data.
|
||||
if (directDatabaseAccess) return true;
|
||||
|
||||
// tell clients to update
|
||||
|
|
|
@ -283,8 +283,6 @@ exports.handleMessage = async (socket, message) => {
|
|||
} else {
|
||||
messageLogger.warn(`Dropped message, unknown COLLABROOM Data Type ${message.data.type}`);
|
||||
}
|
||||
} else if (message.type === 'SWITCH_TO_PAD') {
|
||||
await handleSwitchToPad(socket, message, authorID);
|
||||
} else {
|
||||
messageLogger.warn(`Dropped message, unknown Message Type ${message.type}`);
|
||||
}
|
||||
|
@ -806,44 +804,6 @@ const _correctMarkersInPad = (atext, apool) => {
|
|||
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.
|
||||
const createSessionInfoAuth = (sessionInfo, message) => {
|
||||
// Remember this information since we won't
|
||||
|
|
|
@ -48,8 +48,6 @@ const socketio = require('./socketio');
|
|||
|
||||
const hooks = require('./pluginfw/hooks');
|
||||
|
||||
let receivedClientVars = false;
|
||||
|
||||
// This array represents all GET-parameters which can be used to change a setting.
|
||||
// name: the parameter-name, eg `?noColors=true` => `noColors`
|
||||
// checkVal: the callback is only executed when
|
||||
|
@ -181,8 +179,7 @@ const getUrlVars = () => {
|
|||
return vars;
|
||||
};
|
||||
|
||||
const sendClientReady = (isReconnect, messageType) => {
|
||||
messageType = typeof messageType !== 'undefined' ? messageType : 'CLIENT_READY';
|
||||
const sendClientReady = (isReconnect) => {
|
||||
let padId = document.location.pathname.substring(document.location.pathname.lastIndexOf('/') + 1);
|
||||
// unescape neccesary due to Safari and Opera interpretation of spaces
|
||||
padId = decodeURIComponent(padId);
|
||||
|
@ -201,7 +198,7 @@ const sendClientReady = (isReconnect, messageType) => {
|
|||
|
||||
const msg = {
|
||||
component: 'pad',
|
||||
type: messageType,
|
||||
type: 'CLIENT_READY',
|
||||
padId,
|
||||
sessionID: Cookies.get('sessionID'),
|
||||
token,
|
||||
|
@ -218,6 +215,7 @@ const sendClientReady = (isReconnect, messageType) => {
|
|||
};
|
||||
|
||||
const handshake = () => {
|
||||
let receivedClientVars = false;
|
||||
let padId = document.location.pathname.substring(document.location.pathname.lastIndexOf('/') + 1);
|
||||
// unescape neccesary due to Safari and Opera interpretation of spaces
|
||||
padId = decodeURIComponent(padId);
|
||||
|
@ -394,38 +392,6 @@ const pad = {
|
|||
getUserId: () => pad.myUserInfo.userId,
|
||||
getUserName: () => pad.myUserInfo.name,
|
||||
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) => {
|
||||
pad.collabClient.sendClientMessage(msg);
|
||||
},
|
||||
|
|
|
@ -67,7 +67,7 @@ const padimpexp = (() => {
|
|||
importErrorMessage(message);
|
||||
} else {
|
||||
$('#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'));
|
||||
window.setTimeout(() => $('#importfileinput').removeAttr('disabled'), 0);
|
||||
|
|
Loading…
Reference in New Issue