From dfc8ea4aeabdc4c95df3ab8dfe7b1b2028252e1a Mon Sep 17 00:00:00 2001 From: yetone Date: Fri, 2 Oct 2026 08:02:14 +0800 Subject: [PATCH] =?UTF-8?q?profiles:=20Apply=20closes=20a=20profile's=20de?= =?UTF-8?q?tails,=20and=20their=20=C3=97=20closes=20them=20after=20it=20(#?= =?UTF-8?q?489,=20a=20regression=20of=20#478)=20=E2=80=94=20on=20Apply,=20?= =?UTF-8?q?profileAction=20dropped=20profileOpen=20and=20then=20called=20c?= =?UTF-8?q?loseProfiles,=20whose=20closeProfileDetail,=20finding=20nothing?= =?UTF-8?q?=20open,=20returned=20at=20once;=20renderAgents=20had=20just=20?= =?UTF-8?q?drawn=20the=20details=20again,=20so=20they=20stayed=20in=20the?= =?UTF-8?q?=20window=20and=20came=20back=20with=20the=20tray's=20list,=20a?= =?UTF-8?q?nd=20their=20=C3=97,=20which=20calls=20the=20same=20closeProfil?= =?UTF-8?q?eDetail,=20did=20nothing=20until=20the=20chip=20was=20clicked?= =?UTF-8?q?=20again.=20Apply=20now=20closes=20the=20details=20itself,=20an?= =?UTF-8?q?d=20closeProfileDetail=20closes=20details=20on=20the=20page=20w?= =?UTF-8?q?hether=20or=20not=20profileOpen=20still=20names=20them.=20profi?= =?UTF-8?q?le-confirm.test.cjs=20(Chromium,=20WebKit;=20en,=20zh;=20window?= =?UTF-8?q?=20and=20tray)=20now=20applies=20a=20profile=20from=20its=20det?= =?UTF-8?q?ails=20and=20checks=20they=20close,=20the=20tray's=20list=20ope?= =?UTF-8?q?ns=20again=20on=20the=20chips,=20and=20=C3=97=20closes=20them?= =?UTF-8?q?=20after=20it;=20it=20fails=20without=20the=20change.=20profile?= =?UTF-8?q?-details,=20panel-profiles,=20click-scroll,=20old-webkit=20pass?= =?UTF-8?q?;=20go=20vet,=20go=20build=20-tags=20nogui=20(darwin,=20GOOS=3D?= =?UTF-8?q?linux),=20GOOS=3Dwindows=20go=20build=20pass.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/gui/assets/app.js | 8 +++++-- internal/gui/tests/README.md | 5 +++-- internal/gui/tests/profile-confirm.test.cjs | 24 +++++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/internal/gui/assets/app.js b/internal/gui/assets/app.js index 75036f3a..8a0a3b11 100644 --- a/internal/gui/assets/app.js +++ b/internal/gui/assets/app.js @@ -585,8 +585,9 @@ function toggleProfile(chip, p) { } // closeProfileDetail closes the details shown, if any: false if none were. +// Details on the page close whether or not profileOpen still names them. function closeProfileDetail() { - if (!profileOpen) return false; + if (!profileOpen && !$("#profiles > .prof-detail")) return false; profileOpen = null; $("#profiles > .prof-detail")?.remove(); $(".profiles").classList.remove("detailed"); @@ -2511,7 +2512,10 @@ async function profileAction(action, name, update) { state = data; renderAgents(); if (action === "use") { - profileOpen = null; + // the details close, renderAgents having drawn them again (#489: + // profileOpen dropped first, closeProfileDetail found nothing open and + // left them there, their × doing nothing) + closeProfileDetail(); closeProfiles(); // the agents, as they are now, in sight let msg = t(data.changed === 1 ? "{name} applied · {n} setting changed" : "{name} applied · {n} settings changed", { name, n: data.changed }); const lib = data.library; diff --git a/internal/gui/tests/README.md b/internal/gui/tests/README.md index f927004c..56230a10 100644 --- a/internal/gui/tests/README.md +++ b/internal/gui/tests/README.md @@ -357,8 +357,9 @@ chip's ↻ and × change nothing on a first click, reading "Overwrite?" and "Delete?" instead, and act on a second; the question goes on Escape or when left alone. The details' × closes them, the chip staying where it is; Escape closes the details, then the panel's list, and only then hides the panel; -the list closed with the details open opens again on the chips alone, as -after Apply. In Chromium and WebKit, English and Chinese: +the list closed with the details open opens again on the chips alone; Apply +closes the details, the tray's list opening again on the chips, and their × +closes them after it (#489). In Chromium and WebKit, English and Chinese: ```sh node --test --test-concurrency=1 internal/gui/tests/profile-details.test.cjs internal/gui/tests/panel-profiles.test.cjs internal/gui/tests/profile-confirm.test.cjs diff --git a/internal/gui/tests/profile-confirm.test.cjs b/internal/gui/tests/profile-confirm.test.cjs index 54a7e708..7b7c27eb 100644 --- a/internal/gui/tests/profile-confirm.test.cjs +++ b/internal/gui/tests/profile-confirm.test.cjs @@ -163,6 +163,30 @@ for (const engine of (process.env.BROWSER ? [process.env.BROWSER] : ["chromium", assert.equal(await detail.count(), 0, "closed with the list, the details stay closed"); assert.equal(await home.getAttribute("aria-expanded"), "false"); } else assert.deepEqual(calls, []); + + // Apply closes the details, for good, and × works after it (#489: + // the details stayed, or came back with the list, and their × did + // nothing) + calls.length = 0; // in the panel, the list is open from above + await homeName.click(); + await detail.waitFor(); + await detail.locator(".pd-apply").click(); + await page.waitForFunction(() => document.querySelector("#status").classList.contains("ok")); + assert.deepEqual(calls, ["use home"]); + await page.waitForTimeout(200); + assert.equal(await detail.count(), 0, "Apply closes the details"); + assert.equal(await home.getAttribute("aria-expanded"), "false"); + if (panel) { + assert.equal(await open.count(), 0, "Apply closes the panel's list"); + await openList(); + assert.equal(await detail.count(), 0, "after Apply the list opens on the chips"); + } + await homeName.click(); + await detail.waitFor(); + await detail.locator(".pd-close").click(); + await page.waitForTimeout(200); + assert.equal(await detail.count(), 0, "after Apply the details' × still closes them"); + assert.equal(await home.getAttribute("aria-expanded"), "false"); assert.deepEqual(errors, []); }); }