feat: color file explorer note titles based on status

This commit is contained in:
Aleix Soler 2025-11-21 14:38:17 +01:00
parent 16bcf02039
commit da2572398d
4 changed files with 95 additions and 1 deletions

View file

@ -225,6 +225,17 @@ export const UISettings: React.FC<Props> = ({ settings, onChange }) => {
/>
</SettingItem>
<SettingItem
name="Color filename text using status color"
description="Apply the active status color to the filename text inside the file explorer."
>
<input
type="checkbox"
checked={settings.fileExplorerColorFileName || false}
onChange={handleChange("fileExplorerColorFileName")}
/>
</SettingItem>
<SettingItem
name="Status icon frame"
description="Choose whether to display a frame around the status icon inside the file explorer."

View file

@ -22,6 +22,7 @@ export const DEFAULT_PLUGIN_SETTINGS: PluginSettings = {
customStatuses: [],
showStatusIconsInExplorer: true,
hideUnknownStatusInExplorer: true, // Default to hide unknown status
fileExplorerColorFileName: false,
enabledTemplates: DEFAULT_ENABLED_TEMPLATES,
useCustomStatusesOnly: false,
useMultipleStatuses: true,

View file

@ -6,7 +6,7 @@ import {
} from "@/core/lazyElementObserver";
import { NoteStatusService } from "@/core/noteStatusService";
import settingsService from "@/core/settingsService";
import { GroupedStatuses } from "@/types/noteStatus";
import { GroupedStatuses, NoteStatus } from "@/types/noteStatus";
import { Plugin, TFile, View } from "obsidian";
import { createRoot } from "react-dom/client";
import { StatusesInfoPopup } from "../popups/statusesInfoPopupIntegration";
@ -20,6 +20,8 @@ export class FileExplorerIntegration implements IElementProcessor {
"file-explorer-integration-subscription1";
private readonly FILE_EXPLORER_TYPE = "file-explorer";
private readonly CONTAINER_SELECTOR = ".nav-files-container";
private readonly FILE_NAME_COLORIZED_ATTR = "noteStatusColorized";
private readonly FILE_NAME_ORIGINAL_COLOR_ATTR = "noteStatusOriginalColor";
constructor(plugin: Plugin) {
this.plugin = plugin;
@ -58,6 +60,7 @@ export class FileExplorerIntegration implements IElementProcessor {
key === "fileExplorerIconPosition" ||
key === "fileExplorerIconFrame" ||
key === "fileExplorerIconColorMode" ||
key === "fileExplorerColorFileName" ||
key === "unknownStatusIcon" ||
key === "unknownStatusLucideIcon" ||
key === "unknownStatusColor" ||
@ -104,7 +107,13 @@ export class FileExplorerIntegration implements IElementProcessor {
// Only render icons for markdown files
if (noteStatusService) {
this.applyFileNameColor(
textEl as HTMLElement,
noteStatusService.statuses,
);
this.render(textEl, noteStatusService.statuses);
} else {
this.applyFileNameColor(textEl as HTMLElement, null);
}
}
}
@ -270,4 +279,76 @@ export class FileExplorerIntegration implements IElementProcessor {
this.CONTAINER_SELECTOR,
);
}
private applyFileNameColor(
element?: HTMLElement | null,
statuses?: GroupedStatuses | null,
): void {
if (!element) {
return;
}
if (!settingsService.settings.fileExplorerColorFileName) {
this.clearFileNameColor(element);
return;
}
const primaryStatus = this.getPrimaryStatus(statuses);
if (!primaryStatus) {
this.clearFileNameColor(element);
return;
}
const color = primaryStatus.color?.trim() || this.getFallbackColor();
if (!color) {
this.clearFileNameColor(element);
return;
}
if (!element.dataset[this.FILE_NAME_ORIGINAL_COLOR_ATTR]) {
element.dataset[this.FILE_NAME_ORIGINAL_COLOR_ATTR] =
element.style.color || "";
}
element.dataset[this.FILE_NAME_COLORIZED_ATTR] = "true";
element.style.color = color;
}
private getPrimaryStatus(
statuses?: GroupedStatuses | null,
): NoteStatus | null {
if (!statuses) {
return null;
}
for (const list of Object.values(statuses)) {
if (list.length) {
return list[0];
}
}
return null;
}
private getFallbackColor(): string {
return (
settingsService.settings.unknownStatusColor?.trim() ||
"var(--text-accent)"
);
}
private clearFileNameColor(element: HTMLElement): void {
if (!element.dataset[this.FILE_NAME_COLORIZED_ATTR]) {
return;
}
const previousColor =
element.dataset[this.FILE_NAME_ORIGINAL_COLOR_ATTR] || "";
if (previousColor) {
element.style.color = previousColor;
} else {
element.style.removeProperty("color");
}
delete element.dataset[this.FILE_NAME_ORIGINAL_COLOR_ATTR];
delete element.dataset[this.FILE_NAME_COLORIZED_ATTR];
}
}

View file

@ -23,6 +23,7 @@ export type PluginSettings = {
statusBarShowTemplateName: "always" | "never" | "auto"; // How to show template names in status bar
showStatusIconsInExplorer: boolean;
hideUnknownStatusInExplorer: boolean;
fileExplorerColorFileName: boolean; // Whether to color the file explorer filename text using the current status color
enabledTemplates: string[]; // IDs of enabled templates
useCustomStatusesOnly: boolean; // Whether to use only custom statuses or include templates
useMultipleStatuses: boolean; // Whether to allow multiple statuses per note