pathParam is actually implemented now

the previous commit added the parameter to the signature, documented it, threaded it
through FileBrowserApp — and never used it. seven lines of prose about a feature
that did not exist, committed, deployed, and reported as working.

that one fact explains all three things the owner reported: the query string never
changed because nothing wrote it; refreshing "still went to the right place" because
panelId memory was doing what it has always done; and the preview broke because the
version before it passed `urlPath`, which writes `?view=<name>` — resolvable only
when the folder is in the pathname, which in a panel it is not.

the edit failed silently because I matched on four-space indentation in a file that
uses two, and I did not check. third time today. this one asserts the replacement
changed the file and fails loudly if it did not.

what it does now, for real: current folder read from the named param, written back
with `replace`, base folder expressed as the ABSENCE of the param, and a param
pointing outside `basePath` ignored rather than obeyed — it comes from a URL somebody
can edit, and the jail is the point of an embedded browser.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
This commit is contained in:
2026-08-29 09:08:40 +01:00
co-authored by Claude Opus 5
parent 1da58e5231
commit 0ea4b822ae
@@ -82,14 +82,41 @@ export const useFileBrowserApp = (
// visit still opens at home, because a URL with no `path` means the base. Either way the main
// (unscoped) browser mirrors its folder into files/currentPath so the Create Dashboard flow can
// default a new dashboard's cwd to it.
const currentPath = urlPath ? folderFromPathname(location.pathname) : localPath;
/*
Three sources, mutually exclusive by construction: the pathname for /files, a named query param for
an embedded browser, and component state for an ordinary panel.
A param naming a folder OUTSIDE the jail is ignored rather than obeyed — it arrives from a URL
somebody may have edited, and `basePath` is the whole promise of an embedded browser.
*/
const paramPath = pathParam ? searchParams.get(pathParam) : null;
const currentPath = urlPath
? folderFromPathname(location.pathname)
: pathParam
? paramPath && paramPath.startsWith(basePath)
? paramPath
: basePath
: localPath;
const setCurrentPath = (path: string) => {
// Leaving a folder closes what was open in it. A pane shows a file from the folder you were in, so
// carrying it into the next one leaves the two disagreeing — the listing says one place, the pane
// another. Only the OVERLAY params go; anything else in the query (global UI state) is left alone,
// which is the distinction a wholesale reset kept getting wrong.
if (urlPath) navigate({ pathname: folderHref(path), search: withoutViewerParams(location.search) });
else {
else if (pathParam) {
setSearchParams(
(prev) => {
const next = new URLSearchParams(withoutViewerParams(prev.toString()));
// The base folder is the ABSENCE of the param, so a link to the top of an embedded browser is
// the plain screen URL and nothing accumulates for having gone nowhere.
if (path === basePath) next.delete(pathParam);
else next.set(pathParam, path);
return next;
},
// Browsing folders is not navigation anybody wants twenty back-button presses of.
{ replace: true },
);
} else {
setLocalPath(path);
// Written here rather than in an effect on `currentPath`, so it records a NAVIGATION and not the
// initial render. An effect would fire once on mount with the restored value and persist it back,