From f391bb8eec945ae379ba1cdc1f201b311d022e78 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 13 Dec 2025 13:35:32 +0200 Subject: [PATCH] feat(layout/inline-title): support built-in templates --- .../client/src/widgets/layout/InlineTitle.tsx | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/apps/client/src/widgets/layout/InlineTitle.tsx b/apps/client/src/widgets/layout/InlineTitle.tsx index 8d13d1588..de88b117c 100644 --- a/apps/client/src/widgets/layout/InlineTitle.tsx +++ b/apps/client/src/widgets/layout/InlineTitle.tsx @@ -17,7 +17,7 @@ import { formatDateTime } from "../../utils/formatters"; import NoteIcon from "../note_icon"; import NoteTitleWidget from "../note_title"; import { Badge, BadgeWithDropdown } from "../react/Badge"; -import { FormListItem } from "../react/FormList"; +import { FormDropdownDivider, FormListItem } from "../react/FormList"; import { useNoteBlob, useNoteContext, useNoteProperty, useStaticTooltip, useTriliumEvent } from "../react/hooks"; import { joinElements } from "../react/react_utils"; import { useNoteMetadata } from "../ribbon/NoteInfoTab"; @@ -197,16 +197,32 @@ function MoreNoteTypes({ noteId, restNoteTypes }: { noteId: string, restNoteType } function TemplateNoteTypes({ noteId }: { noteId: string }) { - const [ templates, setTemplates ] = useState([]); + const [ userTemplates, setUserTemplates ] = useState([]); + const [ builtinTemplates, setBuiltinTemplates ] = useState([]); async function refreshTemplates() { const templateNoteIds = await server.get("search-templates"); const templateNotes = await froca.getNotes(templateNoteIds); - setTemplates(templateNotes); + setUserTemplates(templateNotes); + } + + async function loadBuiltinTemplates() { + const templatesRoot = await froca.getNote("_templates"); + if (!templatesRoot) return; + const childNotes = await templatesRoot.getChildNotes(); + const builtinTemplates: FNote[] = []; + for (const childNote of childNotes) { + if (childNote.hasLabel("collection") || !childNote.hasLabel("template")) continue; + builtinTemplates.push(childNote); + } + setBuiltinTemplates(builtinTemplates); } // First load. - useEffect(() => { refreshTemplates(); }, []); + useEffect(() => { + refreshTemplates(); + loadBuiltinTemplates(); + }, []); // React to external changes. useTriliumEvent("entitiesReloaded", ({ loadResults }) => { @@ -220,17 +236,22 @@ function TemplateNoteTypes({ noteId }: { noteId: string }) { text={t("note_title.note_type_switcher_templates")} icon="bx bx-copy-alt" > - {templates.map(template => ( - attributes.setRelation(noteId, "template", template.noteId)} - >{template.title} - ))} + {userTemplates.map(template => )} + {userTemplates.length > 0 && } + {builtinTemplates.map(template => )} ); } +function TemplateItem({ noteId, template }: { noteId: string, template: FNote }) { + return ( + attributes.setRelation(noteId, "template", template.noteId)} + >{template.title} + ); +} + function switchNoteType(noteId: string, { type, mime }: NoteTypeMapping) { return server.put(`notes/${noteId}/type`, { type, mime }); }