Skip to content

fix: use correct target folder for createFolder/uploadFile in Workspace fs#1913

Open
misha-db wants to merge 3 commits into
mainfrom
wsfs-fix-root-folder-creation
Open

fix: use correct target folder for createFolder/uploadFile in Workspace fs#1913
misha-db wants to merge 3 commits into
mainfrom
wsfs-fix-root-folder-creation

Conversation

@misha-db

@misha-db misha-db commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Changes

Fixes title bar click after deselection was targeting the previously selected folder instead of root.

extension.ts

Switches the Workspace FS panel registration from window.registerTreeDataProvider to window.createTreeView so the TreeView handle (which exposes selection) is available. The resulting workspaceFsTreeView is passed to WorkspaceFsCommands and disposed via context.subscriptions.

WorkspaceFsCommands.ts

  • Accepts TreeView as a new constructor parameter (private readonly treeView).
  • Tracks the last left-click–selected item in selectedElement via treeView.onDidChangeSelection (cleared to undefined on deselection).
  • In createFolder and uploadFile, resolves the target folder using a comparison:
    • If element !== treeView.selection[0] — the command was invoked from a context menu on a different item than the current selection → use element.
    • Otherwise — title bar button, or context menu on the already-selected item → use selectedElement (which is undefined if the user deselected before clicking, correctly falling back to the workspace root).

Tests

WorkspaceFsCommands.test.ts

…ce FS

extension.ts

Switches the Workspace FS panel registration from window.registerTreeDataProvider to window.createTreeView so the
TreeView handle (which exposes selection) is available. The resulting workspaceFsTreeView is passed to
WorkspaceFsCommands and disposed via context.subscriptions.

WorkspaceFsCommands.ts

- Accepts TreeView<WorkspaceFsEntity> as a new constructor parameter (private readonly treeView).
- Tracks the last left-click–selected item in selectedElement via treeView.onDidChangeSelection (cleared to
undefined on deselection).
- In createFolder and uploadFile, resolves the target folder using a comparison:
  - If element !== treeView.selection[0] — the command was invoked from a context menu on a different item than the
current selection → use element.
  - Otherwise — title bar button, or context menu on the already-selected item → use selectedElement (which is
undefined if the user deselected before clicking, correctly falling back to the workspace root).

This fixes two bugs:
1. Title bar click after deselection was targeting the previously selected folder instead of root.
2. Context-menu click on a non-selected item was targeting the selected folder instead of the right-clicked one.
@misha-db misha-db requested a review from anton-107 June 16, 2026 15:59
@misha-db misha-db temporarily deployed to test-trigger-is June 16, 2026 15:59 — with GitHub Actions Inactive
@misha-db misha-db requested a review from rugpanov June 16, 2026 16:00
@misha-db misha-db temporarily deployed to test-trigger-is June 16, 2026 16:13 — with GitHub Actions Inactive
@github-actions

Copy link
Copy Markdown
Contributor

If integration tests don't run automatically, an authorized user can run them manually by following the instructions below:

Trigger:
go/deco-tests-run/vscode

Inputs:

  • PR number: 1913
  • Commit SHA: 3e153fe6f2cc032f2f2ada030f611c2ba1c6aa4a

Checks will be approved automatically on success.

@anton-107

Copy link
Copy Markdown
Contributor

Concern: this may not actually fix the reported bug (and the tests don't guard against it)

I traced the logic and I think the core change is effectively a no-op. The key helper:

private resolveTargetElement(element?) {
    return element !== this.treeView.selection[0]
        ? element
        : this.selectedElement;
}

selectedElement is maintained by the listener as this.selectedElement = e.selection[0], so it stays in sync with treeView.selection[0]. At command-invocation time selectedElement === treeView.selection[0]. Substituting that invariant into both branches:

  • element !== selection[0] → returns element
  • element === selection[0] → returns selectedElement (=== selection[0] === element) → also element

So resolveTargetElement(element) reduces to element in every case. The PR swaps element?.path for resolveTargetElement(element)?.path, which yields the same value — behaviorally unchanged.

The tests pass against the original code too. I ran all 13 cases against the pre-PR logic (rootPath = element?.path ?? root, plus the uploadFile DIRECTORY/REPO variant) and every assertion holds — createFolder(entityA)entityA.path, createFolder(undefined) → root, uploadFile(fileEntity) (type FILE) → root, etc. A regression test meant to lock in this fix should fail on the old code; none of these do, so they're validating existing behavior rather than the fix.

Why I don't think the reported bug is addressed. The "title bar after deselection targets the previously selected folder" bug can only occur if, at title-bar-click time, the element/selection VSCode hands the command still points at the stale folder. But in that exact state element === treeView.selection[0] (both stale) and selectedElement tracks the same value — so the new code returns the same stale folder. The deselection test sidesteps this by modeling deselection as simulateSelect(undefined) (everything cleared → root), which is the non-buggy state, rather than reproducing the actual repro.

Possible regression risk. The logic also relies on the assumption (stated in a test comment) that a right-click does not update treeView.selection. If in the running VSCode version a context-menu right-click does update the selection before selectedElement catches up, then "right-click B while A is selected" takes the === branch and returns selectedElement (A) instead of B — creating the folder under the wrong item.

Suggestion: before merging, could you verify the deselection repro empirically with vs. without this diff? If there's a real difference, it'd be worth pinning down exactly what VSCode passes for title-bar vs. context-menu invocations and adding a test that fails on the old code to prove the fix matters. If the intent is "title bar always creates at root, context menu uses the clicked item," distinguishing the two invocation paths explicitly (separate command IDs/args) would be more robust than reconciling element against tracked selection.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants