diff --git a/apps/client/src/widgets/NoteDetail.tsx b/apps/client/src/widgets/NoteDetail.tsx index 8fef34046..14ff0f116 100644 --- a/apps/client/src/widgets/NoteDetail.tsx +++ b/apps/client/src/widgets/NoteDetail.tsx @@ -20,6 +20,7 @@ import Mermaid from "./type_widgets/Mermaid"; import MindMap from "./type_widgets/MindMap"; import { AttachmentDetail, AttachmentList } from "./type_widgets/Attachment"; import ReadOnlyText from "./type_widgets/text/ReadOnlyText"; +import attributes from "../services/attributes"; /** * A `NoteType` altered by the note detail widget, taking into consideration whether the note is editable or not and adding special note types such as an empty one, @@ -35,7 +36,7 @@ type ExtendedNoteType = Exclude | "empty * - Focuses the content when switching tabs. */ export default function NoteDetail() { - const { note, type, noteContext, parentComponent } = useNoteInfo(); + const { note, type, mime, noteContext, parentComponent } = useNoteInfo(); const { ntxId, viewScope } = noteContext ?? {}; const [ correspondingWidget, setCorrespondingWidget ] = useState(); const isFullHeight = checkFullHeight(noteContext, type); @@ -49,6 +50,48 @@ export default function NoteDetail() { }; useEffect(() => setCorrespondingWidget(getCorrespondingWidget(type, props)), [ note, viewScope, type ]); + // Detect note type changes. + useTriliumEvent("entitiesReloaded", async ({ loadResults }) => { + if (!note) return; + + // we're detecting note type change on the note_detail level, but triggering the noteTypeMimeChanged + // globally, so it gets also to e.g. ribbon components. But this means that the event can be generated multiple + // times if the same note is open in several tabs. + + if (note.noteId && loadResults.isNoteContentReloaded(note.noteId, parentComponent.componentId)) { + // probably incorrect event + // calling this.refresh() is not enough since the event needs to be propagated to children as well + // FIXME: create a separate event to force hierarchical refresh + + // this uses handleEvent to make sure that the ordinary content updates are propagated only in the subtree + // to avoid the problem in #3365 + parentComponent.handleEvent("noteTypeMimeChanged", { noteId: note.noteId }); + } else if (note.noteId + && loadResults.isNoteReloaded(note.noteId, parentComponent.componentId) + && (type !== (await getWidgetType(note, noteContext)) || mime !== note?.mime)) { + // this needs to have a triggerEvent so that e.g., note type (not in the component subtree) is updated + parentComponent.triggerEvent("noteTypeMimeChanged", { noteId: note.noteId }); + } else { + const attrs = loadResults.getAttributeRows(); + + const label = attrs.find( + (attr) => + attr.type === "label" && + ["readOnly", "autoReadOnlyDisabled", "cssClass", "displayRelations", "hideRelations"].includes(attr.name ?? "") && + attributes.isAffecting(attr, note) + ); + + const relation = attrs.find((attr) => attr.type === "relation" && ["template", "inherit", "renderNote"] + .includes(attr.name ?? "") && attributes.isAffecting(attr, note)); + + if (note.noteId && (label || relation)) { + // probably incorrect event + // calling this.refresh() is not enough since the event needs to be propagated to children as well + parentComponent.triggerEvent("noteTypeMimeChanged", { noteId: note.noteId }); + } + } + }); + // Automatically focus the editor. useTriliumEvent("activeNoteChanged", () => { // Restore focus to the editor when switching tabs, but only if the note tree is not already focused. @@ -69,11 +112,13 @@ function useNoteInfo() { const { note: actualNote, noteContext, parentComponent } = useNoteContext(); const [ note, setNote ] = useState(); const [ type, setType ] = useState(); + const [ mime, setMime ] = useState(); function refresh() { getWidgetType(actualNote, noteContext).then(type => { setNote(actualNote); setType(type); + setMime(actualNote?.mime); }); } @@ -82,8 +127,9 @@ function useNoteInfo() { if (eventNoteContext?.ntxId !== noteContext?.ntxId) return; refresh(); }); + useTriliumEvent("noteTypeMimeChanged", refresh); - return { note, type, noteContext, parentComponent }; + return { note, type, mime, noteContext, parentComponent }; } function getCorrespondingWidget(noteType: ExtendedNoteType | undefined, props: TypeWidgetProps) { diff --git a/apps/client/src/widgets/note_detail.ts.bak b/apps/client/src/widgets/note_detail.ts.bak index c023217bd..e201a9fed 100644 --- a/apps/client/src/widgets/note_detail.ts.bak +++ b/apps/client/src/widgets/note_detail.ts.bak @@ -186,43 +186,7 @@ export default class NoteDetailWidget extends NoteContextAwareWidget { this.refresh(); } } - - async entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { - // we're detecting note type change on the note_detail level, but triggering the noteTypeMimeChanged - // globally, so it gets also to e.g. ribbon components. But this means that the event can be generated multiple - // times if the same note is open in several tabs. - - if (this.noteId && loadResults.isNoteContentReloaded(this.noteId, this.componentId)) { - // probably incorrect event - // calling this.refresh() is not enough since the event needs to be propagated to children as well - // FIXME: create a separate event to force hierarchical refresh - - // this uses handleEvent to make sure that the ordinary content updates are propagated only in the subtree - // to avoid the problem in #3365 - this.handleEvent("noteTypeMimeChanged", { noteId: this.noteId }); - } else if (this.noteId && loadResults.isNoteReloaded(this.noteId, this.componentId) && (this.type !== (await this.getWidgetType()) || this.mime !== this.note?.mime)) { - // this needs to have a triggerEvent so that e.g., note type (not in the component subtree) is updated - this.triggerEvent("noteTypeMimeChanged", { noteId: this.noteId }); - } else { - const attrs = loadResults.getAttributeRows(); - - const label = attrs.find( - (attr) => - attr.type === "label" && - ["readOnly", "autoReadOnlyDisabled", "cssClass", "displayRelations", "hideRelations"].includes(attr.name ?? "") && - attributeService.isAffecting(attr, this.note) - ); - - const relation = attrs.find((attr) => attr.type === "relation" && ["template", "inherit", "renderNote"].includes(attr.name ?? "") && attributeService.isAffecting(attr, this.note)); - - if (this.noteId && (label || relation)) { - // probably incorrect event - // calling this.refresh() is not enough since the event needs to be propagated to children as well - this.triggerEvent("noteTypeMimeChanged", { noteId: this.noteId }); - } - } - } - + beforeUnloadEvent() { return this.spacedUpdate.isAllSavedAndTriggerUpdate(); }