Skip to content

fix(web): files panel rows that group same-named folders act on their real folder - #339

Merged
LoganRupe merged 2 commits into
LoganRupe:multi-repo-workspacesfrom
dotrahat:fix/335/files-panel-group-rows
Oct 7, 2026
Merged

LoganRupe merged 2 commits into
LoganRupe:multi-repo-workspacesfrom
dotrahat:fix/335/files-panel-group-rows

Conversation

@dotrahat

@dotrahat dotrahat commented Oct 6, 2026 •

Copy link
Copy Markdown

This finishes #335. #336 fixed the right-click actions and drags on files; this fixes the one case left over, a row that groups same-named folders. With both, everything reported in #335 now points at the right file. I re-tested the issue's full example below.

It targets the old files panel code (multi-repo-workspaces-pre-v2). That branch doesn't exist yet, so this targets multi-repo-workspaces at 7e164c78b, the commit it will be cut from. Retarget it once the branch is there.

Problem

When two listed folders share a name, their labels get a parent segment (dupe-a/docs, dupe-b/docs). The tree then shows a dupe-a row that only groups them. Right-click and drag on that row used a path that doesn't exist: <workspace>/dupe-a, or <docs folder>/dupe-a during a search.

Fix

A grouping row now acts on the real folder it stands for, e.g. ~/dev/dupe-test/dupe-a.

Sometimes there is no single folder. The grouped folders can live in different places, belong to an isolated run's worktree, or sit on a drive like C:. Then the row's right-click menu says "No single folder for this group", and dragging the row does nothing. Before, both used a path that doesn't exist.

Testing

All in a macOS build of this branch.

The #335 example (scope-test-four: api, web, notes/2026, ../notes):

Right-click → action Before Now
ideas.md → Reveal in Finder Opened scope-test-four/notes, no ideas.md there Opens ~/dev/notes with ideas.md selected
ideas.md → Open with → VS Code Opened a new, empty file Opens the real file
ideas.md → Copy mention [ideas.md](notes/ideas.md) [ideas.md](/Users/<user>/dev/notes/ideas.md)
ideas.md → Add to chat The agent wasn't sure which ideas.md was meant The agent reads ~/dev/notes/ideas.md directly
plan.md → Reveal in Finder Nothing happened Opens scope-test-four/notes/2026 with plan.md selected
plan.md → Copy mention [plan.md](2026/plan.md) Full path

Isolated run of scope-test, api → WORKTREE.md (a file only in the worktree):

Action Before Now
Reveal in Finder Nothing happened Opens the worktree's api folder with the file selected
Copy mention [WORKTREE.md](api/WORKTREE.md) [WORKTREE.md](/Users/<user>/.t3/worktrees/<…>/api/WORKTREE.md)
Drag into the composer Same wrong path Full worktree path

Same-named folders (dupe-a/docs, dupe-a/notes, dupe-b/docs, dupe-b/notes):

dupe-a row → action Now
Copy mention [dupe-a](/Users/<user>/dev/dupe-test/dupe-a)
Reveal in Finder, with or without a search Opens dupe-test/ with dupe-a selected. During a search it used to do nothing
Reveal in Finder, workspace file in another folder Same. It used to point at a folder that doesn't exist
Drag into the composer Mention has the full path

New unit tests cover the grouping row, a Windows path, a worktree and folders in different places. All web tests pass (5525). In the full suite, a few scripts and server tests fail, but they fail the same way on 7e164c78b without this change.

Found while testing, left for after v2: with same-named folders, clearing a search empties the files panel until it's reopened. That bug is older than this PR, and I have a fix ready.

Fixes #335

Model: Claude Opus 5.5, harness: Claude Code.

… real folder

When two listed folders share a name, their labels grow a parent segment
(`dupe-a/docs`) and the tree shows a `dupe-a` row that only groups them. Its
right-click actions and drag mention joined that segment to the workspace
folder, or during a search to the grouped root, so they pointed at a path that
doesn't exist.

Such a row now resolves to the folder its roots sit in. When they don't share
one, as with an isolated run's worktree, the row has no menu and no mention.

Refs LoganRupe#335

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M labels Oct 6, 2026

@LoganRupe LoganRupe left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good for the same-name case it targets. I found two things worth fixing first:

1. A Windows drive-letter group row resolves to a nonsense path (filePath.ts, rootGroupFolder)

Take roots C:\docs and D:\docs. buildRootLabels labels them C:/docs and D:/docs, so the tree shows a C: row. rootGroupFolder returns C: for that row. fileTreeEntryTarget then finds no separator and returns workspaceRoot: "C", filePath: "C:", so Reveal/Open act on the wrong thing and the mention is drive-relative. Returning null when the candidate has no separator left would cover it:

if (!/[\\/]/.test(candidate)) return null;

2. Dragging only unresolvable rows leaves the row selected (fileTreeDragMention.ts)

When every dragged row's mentionPath is null, handleDragStart returns before draggedPaths = dragged. handleDragEnd then has nothing to deselect, and the gesture's selection stays highlighted. Moving the assignment above the mentions.length === 0 return fixes it. The new test could also assert that deselect was called after handleDragEnd().

Two smaller ones, not blocking:

  • Right-clicking a group row that resolves to null (mixed worktree, or roots in different folders) closes the menu without any feedback, so the row looks broken. A disabled item like "No single folder for this group" would explain it.
  • The search merge still writes root: <docs root>, relativePath: "dupe-a" into entryInfo for the group segment it synthesizes. entryTarget now routes around that, and the only other reader (the file open path) skips directories, so nothing breaks today. Setting root only on segments at or below the root's label would remove the trap.

…nd no shared folder

Review follow-ups for the files panel group rows:

- A group row that is a drive (`C:` over `C:/docs` and `D:/docs`) or a
  network host (`\\server`) now resolves to no folder, rather than one the
  file actions turned into a nonsense path and a drive-relative mention.
- Dragging only rows that can't be mentioned no longer starts a drag. It
  used to select them and drop their tree path into the composer as text.
- Right-clicking a group row with no single folder shows a disabled "No
  single folder for this group" item instead of no menu at all.
- A search no longer gives the group segments it adds above a root's own
  node that root, so nothing can mistake them for a folder inside it.

Refs LoganRupe#335

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@LoganRupe LoganRupe left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for turning this around so quickly. All four points are covered, and moving the search fix to where the group segments get built is better than what I suggested. Cancelling the drag before the tree sees it is a nice touch too, since it means nothing gets left selected.

I checked out the new commit and ran both test files (32 passing) plus a typecheck on apps/web. Both came back clean.

Approving. Thanks again!

@LoganRupe
LoganRupe merged commit 5b16e42 into LoganRupe:multi-repo-workspaces Oct 7, 2026
7 of 16 checks passed
@dotrahat

dotrahat commented Oct 7, 2026

Copy link
Copy Markdown
Author

Thanks for the review! All four points are fixed in 7939537.

1. Drive-letter row. A row that is a drive (C:) or a network host (\\server) now has no folder, so it no longer turns into a wrong path. A share like \\server\share still works. Tests cover all three.

2. Row left selected after a drag. Deselecting at drag end wasn't enough. The tree also puts the row's label on the drag as plain text, so dupe-a/ still landed in the composer. Now, if none of the dragged rows has a real path, the drag is cancelled before the tree sees it. Nothing gets selected and nothing gets dropped. If a selection also has normal files, those still drag.

3. Silent right-click. These rows now show a disabled "No single folder for this group" item. It works in both the desktop and web menus.

4. Search segments. During a search, only the segments from a folder's own row down get its root. The dupe-a row above it no longer does.

All 5,525 web tests pass and the typecheck is clean. I tested the drag and the menu on macOS. The drive and network cases are covered by unit tests only.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants