From de5fbb72837b64c2b35c86a2ed8d905f0239e497 Mon Sep 17 00:00:00 2001 From: Lemon-miaow Date: Sun, 27 Sep 2026 16:08:21 +0800 Subject: [PATCH] =?UTF-8?q?fix(panel):=20LuckPerms=20=E9=A1=B5=E5=9C=A8?= =?UTF-8?q?=E6=89=8B=E6=9C=BA=E4=B8=8A=E7=8E=A9=E5=AE=B6=E6=A0=8F=E6=8C=89?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E6=94=B6=E9=AB=98=E3=80=81=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E5=9C=A8=E5=8D=A1=E5=86=85=E6=BB=9A=E5=8A=A8=EF=BC=8C=E9=80=89?= =?UTF-8?q?=E4=B8=AD=E7=8E=A9=E5=AE=B6=E7=9A=84=E9=9D=A2=E6=9D=BF=E8=90=BD?= =?UTF-8?q?=E5=9C=A8=E9=A6=96=E5=B1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- panel/e2e/mobile.spec.ts | 21 +++++++++++++++++++++ panel/e2e/smoke.spec.ts | 16 ++++++++++++++++ panel/src/pages/ServerLuckPerms.tsx | 10 ++++++---- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/panel/e2e/mobile.spec.ts b/panel/e2e/mobile.spec.ts index 30d9765..275a6e9 100644 --- a/panel/e2e/mobile.spec.ts +++ b/panel/e2e/mobile.spec.ts @@ -20,6 +20,7 @@ for (const [account, path] of [ ["linked", "/account"], ["owner", "/servers"], ["owner", "/admin/users"], + ["owner", "/servers/survival/luckperms"], ] as const) { test(`${path} fits a 375px screen for ${account}`, async ({ page, signIn }) => { await signIn(account); @@ -29,3 +30,23 @@ for (const [account, path] of [ await expectFitsScreen(page); }); } + +test("the LuckPerms player list leaves the rest of the page on the first screen", async ({ page, signIn }) => { + await signIn("owner"); + await page.goto("/servers/survival/luckperms"); + const list = page.getByRole("button", { name: "mock_player", exact: true }).locator(".."); + await expect(list).toBeVisible(); + + // Twelve players online: the list scrolls inside its card, so the prompt + // under it shows without scrolling the page. + await expect(page.getByText(t("servers:luckperms_select_player_prompt"))).toBeInViewport({ ratio: 1 }); + const { scrollHeight, clientHeight } = await list.evaluate((el) => ({ + scrollHeight: el.scrollHeight, + clientHeight: el.clientHeight, + })); + expect(scrollHeight).toBeGreaterThan(clientHeight); + + // The last one is still a tap away. + await page.getByRole("button", { name: "Herobrine", exact: true }).click(); + await expect(page.getByRole("textbox", { name: t("servers:luckperms_player_lookup") })).toHaveValue("Herobrine"); +}); diff --git a/panel/e2e/smoke.spec.ts b/panel/e2e/smoke.spec.ts index e46ba48..900c116 100644 --- a/panel/e2e/smoke.spec.ts +++ b/panel/e2e/smoke.spec.ts @@ -73,3 +73,19 @@ test("a player's pages load on demand and never pull in the admin pages", async await expect.poll(() => fetched.some((p) => ACCOUNT_PAGE.test(p))).toBe(true); expect(fetched.filter((p) => ADMIN_PAGE.test(p))).toEqual([]); }); + +test("on a wide screen the LuckPerms player list runs down its column", async ({ page, signIn }) => { + await signIn("owner"); + await page.goto("/servers/survival/luckperms"); + const list = page.getByRole("button", { name: "mock_player", exact: true }).locator(".."); + await expect(list).toBeVisible(); + + const listBox = (await list.boundingBox())!; + const cardBox = (await list.locator("..").boundingBox())!; + expect(cardBox.height).toBeGreaterThanOrEqual(500); + expect(Math.abs(listBox.y + listBox.height - (cardBox.y + cardBox.height))).toBeLessThanOrEqual(2); + + // A taller screen grows the card to its cap, whatever the roster holds. + await page.setViewportSize({ width: 1280, height: 1000 }); + await expect.poll(async () => (await list.locator("..").boundingBox())!.height).toBe(700); +}); diff --git a/panel/src/pages/ServerLuckPerms.tsx b/panel/src/pages/ServerLuckPerms.tsx index 85d76e4..8f001b7 100644 --- a/panel/src/pages/ServerLuckPerms.tsx +++ b/panel/src/pages/ServerLuckPerms.tsx @@ -397,8 +397,10 @@ export function ServerLuckPerms() { /> ) : (
- {/* Left Directory Sidebar: Single card for Search + Online Players */} - + {/* Left Directory Sidebar: Single card for Search + Online Players. On a + wide screen it fills the column; on a phone it fits its content and the + list scrolls inside it, so the player's panel below is on the first screen. */} + @@ -424,7 +426,7 @@ export function ServerLuckPerms() { {t("access_online_title")}
- + {playersLoading && onlinePlayers.length === 0 ? (
@@ -463,7 +465,7 @@ export function ServerLuckPerms() { {/* Right Main Panel */}
{!selectedPlayer ? ( - +

{t("luckperms_select_player_prompt")}