todo: the files app needs a routing pass

Recorded next to the code-editor entry, since the owner wants both after the
current test pass.

The value is the verified state rather than the request: rows and search results
are opaque-click divs, the breadcrumb is the one surface that already does it
right and is the model to copy, a panel's folder is deliberately not addressable,
and the ephemeral-vs-location param split has no single owner — which is what let
onCloseViewer wipe the location along with the overlay.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-15 20:18:04 +00:00
co-authored by Claude Opus 5
parent 31d8d72527
commit 8e77b9198d
+33
View File
@@ -283,6 +283,39 @@ error boundaries** anywhere in the repo; and `dashboards.id` is a **global** pri
in place via double-click → the viewer's pane. Either `/code-editor` earns its keep as a genuinely
different tool (tree, tabs, multi-file) or that menu item should go.
## Files app — routing
- [ ] **The files app needs a routing pass (noted 2026-08-15, after `31d8d725`).** Do this after the
file-browser test pass, alongside the code-editor work above. `docs/navigation-audit.md` is the
authority and names the anti-pattern; this is where it still lives.
**What prompted it.** Closing a viewer pane sent you back to home. `onCloseViewer` was
`setSearchParams({})` — a wholesale wipe that took `?path=` with it. Fixed, but the shape of the bug
is the point: four handlers touched the same query string and only one of them wiped it, because no
single thing owns that URL.
**Verified state, so the next pass does not have to re-derive it:**
- **Rows are not links.** Both list and grid render a `<div>` with `onDoubleClick`
(`FileItem.tsx:701,748`) — the "opaque click" the audit names. No cmd-click into a new tab, no
middle-click, not link-focusable, and the target is in a closure rather than the DOM.
- **Search results are the same** — `<div onClick={() => handleSearchResultClick(entry)}>`
(`FileViewContainer.tsx:185`), and that handler both navigates the folder AND opens the viewer.
- **The breadcrumb already got it right** and is the model to copy: it renders a real `<Link>` when
given `searchForPath`, and falls back to a `<button>` only for a panel that does not own the
address bar (`Breadcrumb.tsx:21-26`).
- **A panel's folder is not addressable.** `useFileBrowserApp(basePath, root, urlPath)` keeps the
path in the URL only when `urlPath` is true — the `/files` screen. Every panel instance uses local
state, so it always opens at its base and its location cannot be linked or restored. Deliberate as
written; worth re-deciding rather than inheriting.
- **Two path-ish params coexist**: `?path=` is where you are, `?view=` is what is on top. The
ephemeral set (`view`, `ephemeral`, `ephemeral2`, `chatContext`, …) is listed once in
`useFileViewerPanels.EPHEMERAL_KEYS` and that list is the closest thing to an owner.
**The shape of the fix**, if it holds up: rows become `<Link to={{ search: … }}>` like the
breadcrumb, so open-in-new-tab works and the target is in the DOM; one helper owns "set the viewer
params" and "clear the viewer params" so a fifth handler cannot get it wrong the way the fourth did.
## Known bugs
- [ ] **`bootstrap.ts` runs `npm install -g` for Pi on every boot.** `findPiPackageDir` checks stale