feat: add setting to mirror mapped statuses into default tag

This commit is contained in:
Aleix Soler 2025-11-21 18:54:03 +01:00
parent d3f358bc96
commit 82f277e66b
4 changed files with 64 additions and 1 deletions

View file

@ -103,6 +103,19 @@ export const BehaviourSettings: React.FC<Props> = ({ settings, onChange }) => {
/>
</SettingItem>
<SettingItem
name="Write mapped tags to default status tag"
description="When enabled, statuses mapped to custom frontmatter keys are also written to the default status tag."
>
<input
type="checkbox"
checked={settings.writeMappedTagsToDefault || false}
onChange={(e) =>
onChange("writeMappedTagsToDefault", e.target.checked)
}
/>
</SettingItem>
<SettingItem
name="Vault size limit"
description="Disable dashboard and grouped view for vaults with more notes than this limit to improve performance. Set to 0 to disable this feature."

View file

@ -52,4 +52,5 @@ export const DEFAULT_PLUGIN_SETTINGS: PluginSettings = {
editorToolbarButtonDisplay: "all-notes", // Default to show button in all notes
applyStatusRecursivelyToSubfolders: false,
statusFrontmatterMappings: [],
writeMappedTagsToDefault: false,
};

View file

@ -106,6 +106,44 @@ export abstract class BaseNoteStatusService {
return BaseNoteStatusService.resolveStatusFromIdentifier(statusName);
}
protected toScopedStatusName(
status: StatusIdentifier | NoteStatus,
): ScopedStatusName {
if (typeof status === "string") {
return BaseNoteStatusService.parseStatusIdentifier(status);
}
return {
name: status.name,
templateId: status.templateId,
};
}
protected hasExplicitMappingForStatus(
status: StatusIdentifier | NoteStatus,
): boolean {
const mappings =
settingsService.settings.statusFrontmatterMappings ?? [];
if (!mappings.length) {
return false;
}
const scoped = this.toScopedStatusName(status);
return mappings.some((mapping) => {
if (mapping.scope === "status") {
return (
mapping.statusName === scoped.name &&
(mapping.templateId || null) === (scoped.templateId || null)
);
}
if (mapping.scope === "template") {
return (
Boolean(scoped.templateId) &&
mapping.templateId === scoped.templateId
);
}
return false;
});
}
protected getStatusMetadataKeys(): string[] {
return [settingsService.settings.tagPrefix];
}
@ -196,8 +234,9 @@ export class NoteStatusService extends BaseNoteStatusService {
settingsService.settings,
{ isMarkdownFile: true },
);
const defaultKey = settingsService.settings.tagPrefix;
const mappingMatched = this.hasExplicitMappingForStatus(status);
if (
resolved.length === 1 &&
resolved[0] === defaultKey &&
@ -206,6 +245,15 @@ export class NoteStatusService extends BaseNoteStatusService {
resolved = [frontmatterTagName];
}
if (
mappingMatched &&
settingsService.settings.writeMappedTagsToDefault &&
defaultKey &&
this.isMarkdownFile()
) {
resolved = [...resolved, defaultKey];
}
if (options?.includeSourceKey && frontmatterTagName) {
resolved = [...resolved, frontmatterTagName];
}

View file

@ -67,5 +67,6 @@ export type PluginSettings = {
editorToolbarButtonDisplay: "all-notes" | "active-only"; // Whether to show button in all notes or only active one
applyStatusRecursivelyToSubfolders: boolean; // Whether to show recursive folder context option
statusFrontmatterMappings: StatusFrontmatterMapping[]; // Custom mappings between templates/statuses and frontmatter keys
writeMappedTagsToDefault: boolean; // Whether mapped tags should also write to the default tag
[key: string]: unknown;
};