From 87efb807f3bc3c076c94ea825d9a57cfab50cae4 Mon Sep 17 00:00:00 2001 From: Antigravity Date: Sat, 20 Jun 2026 16:27:30 +0000 Subject: [PATCH] =?UTF-8?q?perf:=20debounce=20getHTML()=20dans=20onUpdate?= =?UTF-8?q?=20=E2=80=94=20400ms=20au=20lieu=20de=20chaque=20frappe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit getHTML() traverse tout le document ProseMirror à chaque transaction. Sur les notes longues (500+ blocs), cela causait des lags visibles. Maintenant debounced à 400ms via setTimeout + clearTimeout. Le wikilink detection reste synchrone (réactif). --- memento-note/components/rich-text-editor.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/memento-note/components/rich-text-editor.tsx b/memento-note/components/rich-text-editor.tsx index 5eabdc5..4316ad5 100644 --- a/memento-note/components/rich-text-editor.tsx +++ b/memento-note/components/rich-text-editor.tsx @@ -359,12 +359,21 @@ export const RichTextEditor = forwardRef(null) const onChangeRef = useRef(onChange) onChangeRef.current = onChange + const htmlDebounceRef = useRef | null>(null) const emitContentChange = useCallback((html: string) => { lastEmittedContent.current = html onChangeRef.current?.(html) }, []) + // Debounced version for onUpdate — avoids calling getHTML() on every keystroke + const emitContentChangeDebounced = useCallback((editor: any) => { + if (htmlDebounceRef.current) clearTimeout(htmlDebounceRef.current) + htmlDebounceRef.current = setTimeout(() => { + emitContentChange(editor.getHTML()) + }, 400) + }, [emitContentChange]) + useEffect(() => { if (typeof window === 'undefined') return const checkMobile = () => setIsMobile(window.innerWidth < 768) @@ -595,8 +604,8 @@ export const RichTextEditor = forwardRef { - // Debounce getHTML() — it's expensive on long notes - emitContentChange(e.getHTML()) + // Debounced getHTML() — avoids traversing the whole doc on every keystroke + emitContentChangeDebounced(e) if (!e.isEditable) return const { from, empty } = e.state.selection if (!empty) return