diff --git a/plugins/file-manager/src/frontend/FileManagerSidebar.tsx b/plugins/file-manager/src/frontend/FileManagerSidebar.tsx index 9ad117cb3..a51095ddc 100644 --- a/plugins/file-manager/src/frontend/FileManagerSidebar.tsx +++ b/plugins/file-manager/src/frontend/FileManagerSidebar.tsx @@ -27,7 +27,7 @@ import { removeFolderShortcut, } from "./api/file-manager-data-api"; import { listSSHFiles } from "./api/ssh-file-operations-api"; -import type { DiskFilesystem } from "./disk-info"; +import { mountForPath, type DiskFilesystem } from "./disk-info"; import { toast } from "sonner"; import FolderTree from "./components/FolderTree"; import { @@ -702,11 +702,13 @@ export function FileManagerSidebar({ // ─── Render ─────────────────────────────────────────────────────────────────── const storageFilesystems = diskInfo?.filesystems ?? []; - const activeStorageMount = selectedMount ?? diskInfo?.mount ?? null; + const pathFs = mountForPath(storageFilesystems, currentPath); + const activeStorageMount = + selectedMount ?? pathFs?.mount ?? diskInfo?.mount ?? null; const selectedFs = selectedMount !== null ? (storageFilesystems.find((fs) => fs.mount === selectedMount) ?? null) - : null; + : pathFs; const storage = selectedFs && selectedFs.percent !== null diff --git a/plugins/file-manager/src/frontend/disk-info.ts b/plugins/file-manager/src/frontend/disk-info.ts index 238e82980..2347841ae 100644 --- a/plugins/file-manager/src/frontend/disk-info.ts +++ b/plugins/file-manager/src/frontend/disk-info.ts @@ -20,3 +20,19 @@ export interface HostDiskInfo { mount: string | null; filesystems?: DiskFilesystem[]; } + +/** The filesystem the path lives on: the longest mount point that holds it. */ +export function mountForPath( + filesystems: DiskFilesystem[], + path: string | null | undefined, +): DiskFilesystem | null { + if (!path) return null; + let best: DiskFilesystem | null = null; + for (const fs of filesystems) { + const mount = fs.mount.replace(/\/+$/, "") || "/"; + const inside = + mount === "/" || path === mount || path.startsWith(`${mount}/`); + if (inside && (!best || mount.length > best.mount.length)) best = fs; + } + return best; +} diff --git a/plugins/file-manager/tests/frontend/disk-info.test.ts b/plugins/file-manager/tests/frontend/disk-info.test.ts new file mode 100644 index 000000000..e4ea96ece --- /dev/null +++ b/plugins/file-manager/tests/frontend/disk-info.test.ts @@ -0,0 +1,35 @@ +import { describe, expect, it } from "vitest"; +import { + mountForPath, + type DiskFilesystem, +} from "../../src/frontend/disk-info"; + +function fs(mount: string): DiskFilesystem { + return { + filesystem: mount, + type: "ext4", + mount, + percent: 10, + usedHuman: "1G", + totalHuman: "10G", + availableHuman: "9G", + usedBytes: 1, + totalBytes: 10, + availableBytes: 9, + }; +} + +describe("mountForPath", () => { + const list = [fs("/"), fs("/volume1"), fs("/volume10")]; + + it("picks the deepest mount that holds the path", () => { + expect(mountForPath(list, "/volume1/share")?.mount).toBe("/volume1"); + expect(mountForPath(list, "/volume10")?.mount).toBe("/volume10"); + expect(mountForPath(list, "/etc")?.mount).toBe("/"); + }); + + it("returns null without a path or mounts", () => { + expect(mountForPath(list, null)).toBeNull(); + expect(mountForPath([], "/etc")).toBeNull(); + }); +});