@@ -152,17 +152,9 @@ export default function FileEditorPanel() {
152152
153153 // Tree sidebar state - auto-collapse on mobile
154154 const isMobile = useIsMobile ( ) ;
155- const [ isTreeCollapsed , setIsTreeCollapsed ] = useState ( false ) ;
155+ const [ isTreeCollapsed , setIsTreeCollapsed ] = useState ( isMobile ) ;
156156
157- // Auto-collapse tree sidebar on mobile
158- useEffect ( ( ) => {
159- if ( isMobile ) {
160- setIsTreeCollapsed ( true ) ;
161- }
162- } , [ isMobile ] ) ;
163-
164- // Voice recording state
165- const [ isRecording , setIsRecording ] = useState ( false ) ;
157+ // Voice recording state (derived from recorderControls below)
166158 const recorderControls = useVoiceVisualizer ( ) ;
167159 const { startRecording, stopRecording, isRecordingInProgress, recordedBlob } =
168160 recorderControls ;
@@ -222,14 +214,10 @@ export default function FileEditorPanel() {
222214 // Use activeFile from context (no local selectedFile state needed)
223215 const selectedFile = activeFile ;
224216
225- useEffect ( ( ) => {
226- if ( ! selectedFile ) {
227- latestEditorValueRef . current = "" ;
228- return ;
229- }
230-
231- latestEditorValueRef . current = getFileContent ( selectedFile ) ;
232- } , [ getFileContent , selectedFile ] ) ;
217+ // Keep editor value ref in sync (ref assignment, not state)
218+ latestEditorValueRef . current = selectedFile
219+ ? getFileContent ( selectedFile )
220+ : "" ;
233221
234222 // Parse selected file path into breadcrumb segments
235223 const breadcrumbSegments = useMemo ( ( ) : BreadcrumbSegment [ ] => {
@@ -244,22 +232,10 @@ export default function FileEditorPanel() {
244232 } ) ) ;
245233 } , [ selectedFile ] ) ;
246234
247- // Reset preview when switching to non-previewable file
248- useEffect ( ( ) => {
249- if (
250- selectedFile &&
251- ! isMarkdownFile ( selectedFile ) &&
252- ! isHtmlFile ( selectedFile ) &&
253- ! isMermaidFile ( selectedFile )
254- ) {
255- setShowPreview ( false ) ;
256- }
257- } , [ selectedFile ] ) ;
235+ // effectiveShowPreview is computed below, after helper function definitions
258236
259- // Track recording state changes
260- useEffect ( ( ) => {
261- setIsRecording ( isRecordingInProgress ) ;
262- } , [ isRecordingInProgress ] ) ;
237+ // Use isRecordingInProgress directly instead of syncing to local state
238+ const isRecording = isRecordingInProgress ;
263239
264240 // Handle recorded blob - transcribe and optionally send to LLM for inference
265241 useEffect ( ( ) => {
@@ -487,6 +463,14 @@ export default function FileEditorPanel() {
487463 return filename . toLowerCase ( ) . endsWith ( ".mmd" ) ;
488464 } ;
489465
466+ // Derive effective preview state — disable for non-previewable files
467+ const canPreview =
468+ ! ! selectedFile &&
469+ ( isMarkdownFile ( selectedFile ) ||
470+ isHtmlFile ( selectedFile ) ||
471+ isMermaidFile ( selectedFile ) ) ;
472+ const effectiveShowPreview = showPreview && canPreview ;
473+
490474 // Validate file path
491475 const validatePath = ( path : string , excludePath ?: string ) : string => {
492476 if ( ! path . trim ( ) ) return "Path is required" ;
@@ -1114,17 +1098,17 @@ export default function FileEditorPanel() {
11141098 isHtmlFile ( selectedFile ) ||
11151099 isMermaidFile ( selectedFile ) ) && (
11161100 < Button
1117- variant = { showPreview ? "secondary" : "ghost" }
1101+ variant = { effectiveShowPreview ? "secondary" : "ghost" }
11181102 size = "sm"
11191103 onClick = { ( ) => setShowPreview ( ! showPreview ) }
11201104 className = "h-8 gap-2"
11211105 title = {
1122- showPreview
1106+ effectiveShowPreview
11231107 ? "Show code"
11241108 : `Preview ${ isHtmlFile ( selectedFile ) ? "HTML" : isMermaidFile ( selectedFile ) ? "Mermaid diagram" : "markdown" } `
11251109 }
11261110 aria-label = {
1127- showPreview
1111+ effectiveShowPreview
11281112 ? "Show code"
11291113 : `Preview ${ isHtmlFile ( selectedFile ) ? "HTML" : isMermaidFile ( selectedFile ) ? "Mermaid diagram" : "markdown" } `
11301114 }
@@ -1208,20 +1192,20 @@ export default function FileEditorPanel() {
12081192 < div className = "flex-1 overflow-hidden" >
12091193 { selectedFile && fileSystem . has ( selectedFile ) ? (
12101194 < >
1211- { showPreview && isMarkdownFile ( selectedFile ) ? (
1195+ { effectiveShowPreview && isMarkdownFile ( selectedFile ) ? (
12121196 < ScrollArea className = "h-full" >
12131197 < div className = "p-6 max-w-4xl mx-auto" >
12141198 < MarkdownCard content = { getFileContent ( selectedFile ) } />
12151199 </ div >
12161200 </ ScrollArea >
1217- ) : showPreview && isHtmlFile ( selectedFile ) ? (
1201+ ) : effectiveShowPreview && isHtmlFile ( selectedFile ) ? (
12181202 < iframe
12191203 srcDoc = { getFileContent ( selectedFile ) }
12201204 sandbox = "allow-same-origin"
12211205 className = "w-full h-full border-0 bg-white"
12221206 title = { `Preview of ${ selectedFile } ` }
12231207 />
1224- ) : showPreview && isMermaidFile ( selectedFile ) ? (
1208+ ) : effectiveShowPreview && isMermaidFile ( selectedFile ) ? (
12251209 < ScrollArea className = "h-full" >
12261210 < div className = "p-6 max-w-4xl mx-auto" >
12271211 < MarkdownCard
0 commit comments