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:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user