@@ -2,21 +2,16 @@ import React, { useState, useEffect, useRef } from "react";
22import { api } from "../services/api" ;
33import VersionHistory from "./VersionHistory" ;
44import { Attachments } from "./Attachments" ;
5+ import { useEditorStore } from "../store/editorStore" ;
56import "./Editor.css" ;
67
78interface EditorProps {
89 pagePath : string | null ;
910 onClose : ( ) => void ;
10- onContentChange ?: ( content : string ) => void ;
11- onScroll ?: ( percent : number ) => void ;
1211}
1312
14- export const Editor : React . FC < EditorProps > = ( {
15- pagePath,
16- onClose,
17- onContentChange,
18- onScroll,
19- } ) => {
13+ export const Editor : React . FC < EditorProps > = ( { pagePath, onClose } ) => {
14+ const { setContent : setStoreContent , scrollEditor } = useEditorStore ( ) ;
2015 const [ content , setContent ] = useState ( "" ) ;
2116 const [ isSaving , setIsSaving ] = useState ( false ) ;
2217 const [ isLoading , setIsLoading ] = useState ( false ) ;
@@ -29,6 +24,7 @@ export const Editor: React.FC<EditorProps> = ({
2924 const [ isListening , setIsListening ] = useState ( false ) ;
3025 const textareaRef = useRef < HTMLTextAreaElement > ( null ) ;
3126 const scrollThrottleRef = useRef < number | null > ( null ) ;
27+ const debounceTimerRef = useRef < NodeJS . Timeout | null > ( null ) ;
3228 // eslint-disable-next-line @typescript-eslint/no-explicit-any
3329 const recognitionRef = useRef < any > ( null ) ;
3430 const contentRef = useRef < string > ( content ) ; // Track current content for speech recognition
@@ -38,11 +34,29 @@ export const Editor: React.FC<EditorProps> = ({
3834 contentRef . current = content ;
3935 } , [ content ] ) ;
4036
37+ // Debounced store update - only update preview after typing pauses
38+ useEffect ( ( ) => {
39+ if ( debounceTimerRef . current ) {
40+ clearTimeout ( debounceTimerRef . current ) ;
41+ }
42+
43+ debounceTimerRef . current = setTimeout ( ( ) => {
44+ setStoreContent ( content ) ;
45+ } , 600 ) ; // 600ms debounce
46+
47+ return ( ) => {
48+ if ( debounceTimerRef . current ) {
49+ clearTimeout ( debounceTimerRef . current ) ;
50+ }
51+ } ;
52+ } , [ content , setStoreContent ] ) ;
53+
4154 useEffect ( ( ) => {
4255 if ( pagePath ) {
4356 loadPage ( ) ;
4457 } else {
4558 setContent ( "" ) ;
59+ setStoreContent ( "" ) ;
4660 setError ( null ) ;
4761 }
4862 } , [ pagePath ] ) ;
@@ -55,10 +69,8 @@ export const Editor: React.FC<EditorProps> = ({
5569 try {
5670 const page = await api . getPage ( pagePath ) ;
5771 setContent ( page . content ) ;
58- // Notify parent of initial content
59- if ( onContentChange ) {
60- onContentChange ( page . content ) ;
61- }
72+ // Update store with initial content
73+ setStoreContent ( page . content ) ;
6274 } catch ( err ) {
6375 console . error ( "Failed to load page:" , err ) ;
6476 setError ( "Failed to load page. Click to retry." ) ;
@@ -117,8 +129,6 @@ export const Editor: React.FC<EditorProps> = ({
117129
118130 // Handle editor scroll - sends scroll position to preview (throttled)
119131 const handleScroll = ( e : React . UIEvent < HTMLTextAreaElement > ) => {
120- if ( ! onScroll ) return ;
121-
122132 const target = e . currentTarget ;
123133 const scrollTop = target . scrollTop ;
124134 const maxScroll = target . scrollHeight - target . clientHeight ;
@@ -129,7 +139,7 @@ export const Editor: React.FC<EditorProps> = ({
129139 scrollThrottleRef . current = requestAnimationFrame ( ( ) => {
130140 scrollThrottleRef . current = null ;
131141 if ( maxScroll > 0 ) {
132- onScroll ( scrollTop / maxScroll ) ;
142+ scrollEditor ( scrollTop / maxScroll ) ;
133143 }
134144 } ) ;
135145 } ;
@@ -174,9 +184,7 @@ export const Editor: React.FC<EditorProps> = ({
174184 currentContent . slice ( end ) ;
175185
176186 setContent ( newContent ) ;
177- if ( onContentChange ) {
178- onContentChange ( newContent ) ;
179- }
187+ // Store update is debounced via useEffect
180188
181189 // Move cursor to end of inserted text
182190 const newCursorPos = start + finalTranscript . length ;
@@ -241,9 +249,7 @@ export const Editor: React.FC<EditorProps> = ({
241249 const end = textarea . selectionEnd ;
242250 const newContent = content . substring ( 0 , start ) + text + content . substring ( end ) ;
243251 setContent ( newContent ) ;
244- if ( onContentChange ) {
245- onContentChange ( newContent ) ;
246- }
252+ // Store update is debounced via useEffect
247253 }
248254 } ;
249255
@@ -656,10 +662,7 @@ export const Editor: React.FC<EditorProps> = ({
656662 value = { content }
657663 onChange = { ( e ) => {
658664 setContent ( e . target . value ) ;
659- // Notify parent of content change immediately for live preview
660- if ( onContentChange ) {
661- onContentChange ( e . target . value ) ;
662- }
665+ // Store update is debounced via useEffect
663666 } }
664667 onScroll = { handleScroll }
665668 onKeyDown = { handleKeyDown }
0 commit comments