From 0ea4b822ae82e091af6eb9d4d6f42b70a793a42e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Sat, 29 Aug 2026 09:08:40 +0100 Subject: [PATCH] pathParam is actually implemented now MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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=` — 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 Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043 --- .../FileBrowserApp/useFileBrowserApp.ts | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/workspaces/officerdev/src/apps/FileBrowser/FileBrowserApp/useFileBrowserApp.ts b/src/workspaces/officerdev/src/apps/FileBrowser/FileBrowserApp/useFileBrowserApp.ts index 616bb5a6..1bd3ed45 100644 --- a/src/workspaces/officerdev/src/apps/FileBrowser/FileBrowserApp/useFileBrowserApp.ts +++ b/src/workspaces/officerdev/src/apps/FileBrowser/FileBrowserApp/useFileBrowserApp.ts @@ -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,