feat(project-view): show Maven and Gradle module folders in bold (#835)

Module folders below the project root are shown in bold in the Project view, from the same build presentation the module icons use; the root and plain folders keep their style.

Fixes #813

Co-authored-by: kevinh458 <[email protected]>
Цей коміт міститься в:
kevinh authored and GitHub committed 2026-11-02 20:13:31 +08:00
1 джерело 64b8b5cea9
коміт 2a6cc686eb
4 files changed
+31 -2

No files matched your search

+3
Переглянути файл
@@ -40,6 +40,9 @@
color: var(--fg-strong);
font-weight: 600;
}
.moduleLabel {
font-weight: 600;
}
/* IDEA's "excluded" look: ignored / excluded entries are dimmed. */
.excluded {
color: var(--vcs-ignored);
+10 -1
Переглянути файл
@@ -48,7 +48,12 @@ import { badgeKind } from "@/ui/symbolKind";
import { contextMenuItems, menuGroupContext, newMenuItems } from "./contextMenu";
import { openNewPopup } from "./newPopupModel";
import { presentationIcon, useJvmPresentation } from "@/platform/filePresentation";
import { moduleFolderIcon, useProjectPresentation, type BuildPresentation } from "@/platform/projectPresentation";
import {
isModuleFolder,
moduleFolderIcon,
useProjectPresentation,
type BuildPresentation,
} from "@/platform/projectPresentation";
import { relativePath } from "@/platform/project";
import { folderKind } from "./folderKind";
import { useHomeDir } from "./home";
@@ -270,6 +275,8 @@ const Row = memo(function Row({
node.dir || node.placeholder || node.icon
? iconFor(node, roots, root, build, detected)
: presentationIcon(node.path, file, roots, root, build.spring);
const moduleFolder =
node.dir && !node.placeholder && !!root && isModuleFolder(relativePath(root, node.path), node.root, build.modules);
const isEditing =
!!editing && (node.placeholder ? editing.kind === "new" : editing.kind === "rename" && editing.key === node.key);
const faded = node.ignored || deco.faded;
@@ -310,6 +317,8 @@ const Row = memo(function Row({
node.root && styles.rootName,
// Only the project itself is bold (IDEA); contributed roots like Scratches are not.
node.root && !node.icon && styles.rootLabel,
// Maven / Gradle module folders are bold too, as in IDEA.
moduleFolder && styles.moduleLabel,
faded && !deco.color && styles.excluded,
deco.error && styles.error,
)}
+13 -1
Переглянути файл
@@ -1,5 +1,5 @@
import { describe, it, expect } from "vitest";
import { buildPresentation, moduleFolderIcon } from "./projectPresentation";
import { buildPresentation, isModuleFolder, moduleFolderIcon } from "./projectPresentation";
import type { BuildModel } from "./ipc";
const model = (partial: unknown) => ({ maven: null, gradle: null, ...(partial as object) }) as BuildModel;
@@ -13,6 +13,18 @@ describe("build presentation context", () => {
expect(moduleFolderIcon("app", false, modules)).toBe(`${tool}-module`);
expect(moduleFolderIcon("plain", false, modules)).toBeNull();
});
it("marks nested module folders, not the project root or plain folders", () => {
const modules = new Map<string, "maven" | "gradle">([
["", "maven"],
["core", "maven"],
["services/api", "gradle"],
]);
expect(isModuleFolder("core", false, modules)).toBe(true);
expect(isModuleFolder("services/api", false, modules)).toBe(true);
expect(isModuleFolder("", true, modules)).toBe(false);
expect(isModuleFolder("services", false, modules)).toBe(false);
expect(isModuleFolder("core/src", false, modules)).toBe(false);
});
it("includes Maven aggregators and modules without source roots", () => {
const context = buildPresentation(
model({
+5
Переглянути файл
@@ -24,6 +24,11 @@ export function buildPresentation(model: BuildModel): BuildPresentation {
return { modules, spring };
}
/** A Maven / Gradle module folder below the project root: IDEA shows its name in bold. */
export function isModuleFolder(rel: string, root: boolean, modules: BuildPresentation["modules"]): boolean {
return !root && rel !== "" && modules.has(rel);
}
export function moduleFolderIcon(rel: string, root: boolean, modules: BuildPresentation["modules"]): string | null {
const tool = modules.get(rel);
return tool ? `${tool}-${root ? "project" : "module"}` : null;