mirror of
https://github.com/ether/etherpad-lite.git
synced 2026-07-17 16:47:05 +00:00
fix(pad): keep menu_right visible on readonly pads by default (#7783)
PR #X (issue #5182) added a client-side `$('#editbar .menu_right').hide()` for readonly pads, opt-out via `?showMenuRight=true`. The intent — clean chrome for iframe-embedded readonly announcement pads — was good but the implementation hid the userlist toggle along with import/export. That has two unwanted effects on non-embed deployments: * Plugins like ep_guest inject their "Log In" button into `#myuser` inside the userlist popup, which lives under `.menu_right`. When the guest user (readOnly: true) lands on a readonly pad, the button they need to escape readonly is hidden. Chicken-and-egg. * Settings, embed, home, timeslider, showusers are all legitimately useful for readonly viewers and got removed alongside the actual write-only controls. The server already does the right thing without help from the client: * src/node/utils/toolbar.ts:282-290 strips `savedrevision` from the right toolbar when isReadOnly is true. * src/static/css/pad/popup_import_export.css:1 has `.readonly .acl-write { display: none }`, which hides the Import column of the import/export popup. Export stays visible (and is legitimately useful in readonly). Drop the client-side blanket hide. The iframe-embed use case from #5182 is still served by `?showMenuRight=false` (the existing handler at src/static/js/pad.ts:91-107), and `?showControls=false` continues to hide the entire editbar for callers who want even the left menu gone. Tests: rewrite `hide_menu_right.spec.ts`. The "readonly pad hides .menu_right by default" assertion is inverted; a new test confirms `?showMenuRight=false` still hides on readonly pads. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
294158e773
commit
8c4f974122
2 changed files with 34 additions and 13 deletions
|
|
@ -91,10 +91,12 @@ const getParameters = [
|
|||
},
|
||||
{
|
||||
// showMenuRight accepts 'true' or 'false'. Explicit 'false' hides the
|
||||
// right-side toolbar (import/export/timeslider/settings/share/users);
|
||||
// explicit 'true' forces it visible, overriding the readonly
|
||||
// auto-hide applied further down (issue #5182). Any other value is
|
||||
// a no-op — the menu stays in its default state.
|
||||
// right-side toolbar (import/export/timeslider/settings/embed/home/
|
||||
// users) — useful for iframe-embedded readonly pads where the menu
|
||||
// is just chrome (issue #5182). Explicit 'true' forces the menu
|
||||
// visible (a no-op against the default, kept for symmetry and for
|
||||
// overriding any future caller-applied hide). Any other value is a
|
||||
// no-op — the menu stays in its default state.
|
||||
name: 'showMenuRight',
|
||||
checkVal: null,
|
||||
callback: (val) => {
|
||||
|
|
@ -787,14 +789,18 @@ const pad = {
|
|||
$('#chaticon').hide();
|
||||
$('#options-chatandusers').parent().hide();
|
||||
$('#options-stickychat').parent().hide();
|
||||
// Hide the right-side toolbar on readonly pads — import/export,
|
||||
// timeslider, settings, share, users are all noise for viewers
|
||||
// who can't interact with the pad. Callers who need those
|
||||
// controls visible on a readonly pad can force them back via
|
||||
// `?showMenuRight=true`, which runs in getParameters() above.
|
||||
if (getUrlVars().get('showMenuRight') !== 'true') {
|
||||
$('#editbar .menu_right').hide();
|
||||
}
|
||||
// The right-side toolbar stays visible on readonly pads. The
|
||||
// server-side `toolbar.menu(buttons, isReadOnly)` (see
|
||||
// src/node/utils/toolbar.ts) already strips `savedrevision`, and
|
||||
// `.readonly .acl-write { display: none }` hides the Import column
|
||||
// inside the import/export popup, so the remaining controls
|
||||
// (export, timeslider, settings, embed, home, showusers) are all
|
||||
// safe for readonly viewers — and the userlist is the surface that
|
||||
// plugins like ep_guest hang their "Log In" button off, so hiding
|
||||
// it traps guests in readonly with no way out. Iframe-embed use
|
||||
// cases that want a clean look (issue #5182) opt in to the hide
|
||||
// via `?showMenuRight=false`, or hide the whole editbar via
|
||||
// `?showControls=false`.
|
||||
} else if (!settings.hideChat) { $('#chaticon').show(); }
|
||||
|
||||
$('body').addClass(window.clientVars.readonly ? 'readonly' : 'readwrite');
|
||||
|
|
|
|||
|
|
@ -44,10 +44,25 @@ test.describe('showMenuRight URL parameter', function () {
|
|||
return url;
|
||||
};
|
||||
|
||||
test('readonly pad hides .menu_right by default', async function ({page}) {
|
||||
test('readonly pad shows .menu_right by default', async function ({page}) {
|
||||
// The server-side toolbar.menu(..., isReadOnly) strips `savedrevision`
|
||||
// and `.readonly .acl-write { display: none }` hides the Import
|
||||
// column of the import/export popup, so the remaining controls
|
||||
// (export, timeslider, settings, embed, home, showusers) are safe
|
||||
// for readonly viewers — and ep_guest / other auth plugins depend
|
||||
// on the userlist being reachable to surface their Log In button.
|
||||
const readonlyUrl = await getReadonlyUrl(page);
|
||||
await page.goto(readonlyUrl);
|
||||
await page.waitForSelector('#editorcontainer.initialized');
|
||||
await expect(page.locator('#editbar .menu_right')).toBeVisible();
|
||||
});
|
||||
|
||||
test('readonly pad with showMenuRight=false hides the menu', async function ({page}) {
|
||||
// Iframe-embed use case (issue #5182): the embedder opts in to the
|
||||
// hide via the URL parameter when they want a clean look.
|
||||
const readonlyUrl = await getReadonlyUrl(page);
|
||||
await page.goto(`${readonlyUrl}?showMenuRight=false`);
|
||||
await page.waitForSelector('#editorcontainer.initialized');
|
||||
await expect(page.locator('#editbar .menu_right')).toBeHidden();
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue