From 4da3e8a4d88caf9be7bdbb42d78e25b4618a5159 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Thu, 21 Aug 2025 10:53:59 +0300 Subject: [PATCH] refactor(react/note_title): use note property for title as well --- apps/client/src/widgets/note_title.tsx | 20 +++++++------------- apps/client/src/widgets/react/hooks.tsx | 21 +++++++++++++++++---- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/apps/client/src/widgets/note_title.tsx b/apps/client/src/widgets/note_title.tsx index eefb71184..c23cea833 100644 --- a/apps/client/src/widgets/note_title.tsx +++ b/apps/client/src/widgets/note_title.tsx @@ -1,41 +1,35 @@ -import { useEffect, useRef, useState } from "preact/hooks"; +import { useRef } from "preact/hooks"; import { t } from "../services/i18n"; import FormTextBox from "./react/FormTextBox"; -import { useNoteContext, useNoteProperty, useSpacedUpdate, useTriliumEventBeta } from "./react/hooks"; +import { useNoteContext, useNoteProperty, useSpacedUpdate } from "./react/hooks"; import protected_session_holder from "../services/protected_session_holder"; import server from "../services/server"; import "./note_title.css"; export default function NoteTitleWidget() { const { note, noteId, componentId } = useNoteContext(); - const [ title, setTitle ] = useState(note?.title); + const title = useNoteProperty(note, "title", componentId); const isProtected = useNoteProperty(note, "isProtected"); - useEffect(() => setTitle(note?.title), [ note?.noteId ]); + const newTitle = useRef(""); const spacedUpdate = useSpacedUpdate(async () => { if (!note) { return; } protected_session_holder.touchProtectedSessionIfNecessary(note); - await server.put(`notes/${noteId}/title`, { title: title }, componentId); + await server.put(`notes/${noteId}/title`, { title: newTitle.current }, componentId); }); - useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => { - if (loadResults.isNoteReloaded(noteId, componentId)) { - setTitle(note?.title); - } - }); - return (
{ - setTitle(newValue); + newTitle.current = newValue; spacedUpdate.scheduleUpdate(); }} /> diff --git a/apps/client/src/widgets/react/hooks.tsx b/apps/client/src/widgets/react/hooks.tsx index bc96b780b..1097f7d9c 100644 --- a/apps/client/src/widgets/react/hooks.tsx +++ b/apps/client/src/widgets/react/hooks.tsx @@ -264,17 +264,30 @@ export function useNoteContext() { } -export function useNoteProperty(note: FNote | null | undefined, property: T) { +/** + * Allows a React component to listen to obtain a property of a {@link FNote} while also automatically watching for changes, either via the user changing to a different note or the property being changed externally. + * + * @param note the {@link FNote} whose property to obtain. + * @param property a property of a {@link FNote} to obtain the value from (e.g. `title`, `isProtected`). + * @param componentId optionally, constricts the refresh of the value if an update occurs externally via the component ID of a legacy widget. This can be used to avoid external data replacing fresher, user-inputted data. + * @returns the value of the requested property. + */ +export function useNoteProperty(note: FNote | null | undefined, property: T, componentId?: string) { if (!note) { return null; } - + const [ value, setValue ] = useState(note[property]); - useEffect(() => setValue(value), [ note[property] ]); + + // Watch for note changes. + useEffect(() => setValue(note[property]), [ note[property] ]); + + // Watch for external changes. useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => { - if (loadResults.isNoteReloaded(note.noteId)) { + if (loadResults.isNoteReloaded(note.noteId, componentId)) { setValue(note[property]); } }); + return value; } \ No newline at end of file