Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit b2417977f0616dce23272efdf1f44816dbf8c519
parent 2ee0e932dff1a389c6fb7a1a1dbbfc838d5b882b
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Tue, 29 Sep 2026 23:39:12 -0400

editor: the picker drops a held choice once the URL moves

A choice made on a site's page (or a ?site= link's page) is held for the URL
it was made on, so the controlled select shows it while the navigation it
starts is in flight. The hold was ignored on other URLs but never cleared, so
Back to the page it was made on showed the old choice over the path. It is now
dropped on the first render at another URL. New site-scope case: Back from
/sites/beta/charts to /sites/alpha/charts shows alpha (received "beta" without
the fix).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Diffstat:
Meditor/app/components/SiteScopeSelect.tsx | 5++++-
Meditor/e2e/site-scope.spec.ts | 16++++++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/editor/app/components/SiteScopeSelect.tsx b/editor/app/components/SiteScopeSelect.tsx @@ -32,11 +32,14 @@ export function SiteScopeSelect({ sites }: { sites: SiteScopeOption[] }) { // A controlled <select> snaps back to its value when the change does not // re-render it with the new one. Where the path or the param outranks the // stored value, the choice is held here for the URL it was made on, so the - // select shows it until the navigation it starts replaces that URL. + // select shows it until the navigation it starts replaces that URL. Once the + // URL has moved it is dropped, so coming back to that URL later (Back, or a + // link) shows what the URL says, not an old choice. const urlKey = `${pathname}?${search}`; const [pending, setPending] = useState<{ urlKey: string; value: string } | null>( null, ); + if (pending !== null && pending.urlKey !== urlKey) setPending(null); const held = pending?.urlKey === urlKey ? pending.value : null; const resolved = resolveActiveSiteFrom( [held, onSite?.siteId, param, stored], diff --git a/editor/e2e/site-scope.spec.ts b/editor/e2e/site-scope.spec.ts @@ -340,3 +340,19 @@ test("a choice the old picker kept in localStorage moves to the cookie once", as await expect.poll(legacy, { timeout: 15_000 }).toBeNull(); expect(await storedCookie(page)).toBe("beta"); }); + +test("Back to a site's page shows that site, not the choice made there", async ({ + page, +}) => { + await twoSites(); + const picker = page.getByLabel("Active site"); + await page.goto("/sites/alpha/charts"); + await hydrated(page); + // The choice is held on the page it was made on until the push lands… + await picker.selectOption("beta"); + await expect(page).toHaveURL(/\/sites\/beta\/charts$/); + // …and dropped once the URL has moved: back on alpha's page, the path rules. + await page.goBack(); + await expect(page).toHaveURL(/\/sites\/alpha\/charts$/); + await expect(picker).toHaveValue("alpha"); +});