fix(project-tree): reveal WSL paths through the wsl.localhost share (#1806)

* fix(project-tree): reveal WSL paths through the wsl.localhost share

"Reveal in Explorer" in a WSL project passed the distro-internal
/home/... path to revealItemInDir, which read it as a local path and
reported it missing. Translate to the \\wsl.localhost\<distro>\...
UNC share before revealing.

* fix(project-tree): match reveal failure title to the local file manager
This commit is contained in:
arookieofc authored and GitHub committed 2026-11-06 21:52:34 +08:00
1 parent b6dfde07bf
commit a3ca40ccf4
2 files changed
+59 -3

No files matched your search

@@ -7,6 +7,7 @@ import {
importExternal,
paste,
refreshOsClipboard,
revealablePath,
selectionAfterDelete,
transfer,
topLevelPaths,
@@ -452,3 +453,43 @@ describe("project clipboard ownership", () => {
expect(canPaste()).toBe(true);
});
});
describe("revealablePath", () => {
const platform = usePlatform.getState();
afterEach(() => {
usePlatform.setState(platform);
useRemote.setState({ session: null });
});
it("translates distro paths to the \\\\wsl.localhost share for a WSL session on Windows", () => {
usePlatform.setState({ os: "windows" });
useRemote.setState({
session: {
target: { kind: "wsl", distro: "Ubuntu-24.04" },
root: "/p",
host: "Ubuntu",
os: "linux",
commands: [],
},
});
expect(revealablePath("/home/me/app/src/main.rs")).toBe(
"\\\\wsl.localhost\\Ubuntu-24.04\\home\\me\\app\\src\\main.rs",
);
expect(revealablePath("/")).toBe("\\\\wsl.localhost\\Ubuntu-24.04\\");
});
it("leaves paths alone for local projects, SSH sessions and non-Windows desktops", () => {
usePlatform.setState({ os: "windows" });
useRemote.setState({
session: { target: { kind: "ssh", config: "host" }, root: "/p", host: "host", os: "linux", commands: [] },
});
expect(revealablePath("/home/me/app")).toBe("/home/me/app");
useRemote.setState({ session: null });
expect(revealablePath("C:\\work\\app")).toBe("C:\\work\\app");
usePlatform.setState({ os: "macos" });
useRemote.setState({
session: { target: { kind: "wsl", distro: "Ubuntu" }, root: "/p", host: "Ubuntu", os: "linux", commands: [] },
});
expect(revealablePath("/home/me/app")).toBe("/home/me/app");
});
});
+18 -3
View File
@@ -39,7 +39,7 @@ import {
useProjectTree,
} from "./store";
import { tx } from "@/platform/i18n";
import { hostOs, isRemoteWindow } from "@/platform/remote";
import { hostOs, isRemoteWindow, useRemote } from "@/platform/remote";
import { usePlatform } from "@/platform/platformInfo";
/** Nodes that may be renamed, moved or deleted (not roots, groups or library sources). */
@@ -821,14 +821,29 @@ export async function copyPaths(kind: PathKind, nodes: ProjectNode[] = selectedN
}
}
/**
* The path the local OS's file manager can open: in a WSL session the node
* paths are inside the distro (`/home/…`), which `revealItemInDir` reads as
* local paths — translate them to `\\wsl.localhost\<distro>\…` UNC shares.
*/
export function revealablePath(path: string): string {
const session = useRemote.getState().session;
if (session?.target.kind !== "wsl" || usePlatform.getState().os !== "windows") return path;
if (!path.startsWith("/")) return path;
return `\\\\wsl.localhost\\${session.target.distro}${path.replaceAll("/", "\\")}`;
}
export async function revealInFinder(nodes: ProjectNode[] = selectedNodes()) {
const paths = nodes.map((n) => n.path);
const paths = nodes.map((n) => revealablePath(n.path));
if (!paths.length) return;
try {
const { revealItemInDir } = await import("@tauri-apps/plugin-opener");
await revealItemInDir(paths.length === 1 ? paths[0]! : paths);
} catch (e) {
fail("Cannot reveal in Finder", e);
// Same names as contextMenu.revealLabel (kept local: contextMenu imports
// this module, so importing it back would be a cycle).
const desktop = usePlatform.getState().os;
fail(`Cannot reveal in ${desktop === "windows" ? "Explorer" : desktop === "linux" ? "Files" : "Finder"}`, e);
}
}