@@ -5,6 +5,7 @@ import { createLogger } from '@sim/logger'
55import { useParams } from 'next/navigation'
66import {
77 Button ,
8+ Columns2 ,
89 Download ,
910 DropdownMenu ,
1011 DropdownMenuContent ,
@@ -48,6 +49,7 @@ import {
4849 ResourceHeader ,
4950 timeCell ,
5051} from '@/app/workspace/[workspaceId]/components'
52+ import type { PreviewMode } from '@/app/workspace/[workspaceId]/files/components/file-viewer'
5153import {
5254 FileViewer ,
5355 isPreviewable ,
@@ -157,7 +159,7 @@ export function Files() {
157159 const [ creatingFile , setCreatingFile ] = useState ( false )
158160 const [ isDirty , setIsDirty ] = useState ( false )
159161 const [ saveStatus , setSaveStatus ] = useState < SaveStatus > ( 'idle' )
160- const [ showPreview , setShowPreview ] = useState ( true )
162+ const [ previewMode , setPreviewMode ] = useState < PreviewMode > ( 'preview' )
161163 const [ showUnsavedChangesAlert , setShowUnsavedChangesAlert ] = useState ( false )
162164 const [ showDeleteConfirm , setShowDeleteConfirm ] = useState ( false )
163165 const [ contextMenuFile , setContextMenuFile ] = useState < WorkspaceFileRecord | null > ( null )
@@ -312,7 +314,7 @@ export function Files() {
312314 if ( isDirty ) {
313315 setShowUnsavedChangesAlert ( true )
314316 } else {
315- setShowPreview ( false )
317+ setPreviewMode ( 'editor' )
316318 setSelectedFileId ( null )
317319 }
318320 } , [ isDirty ] )
@@ -382,13 +384,11 @@ export function Files() {
382384 ]
383385 )
384386
385- const handleTogglePreview = useCallback ( ( ) => setShowPreview ( ( prev ) => ! prev ) , [ ] )
386-
387387 const handleDiscardChanges = useCallback ( ( ) => {
388388 setShowUnsavedChangesAlert ( false )
389389 setIsDirty ( false )
390390 setSaveStatus ( 'idle' )
391- setShowPreview ( false )
391+ setPreviewMode ( 'editor' )
392392 setSelectedFileId ( null )
393393 } , [ ] )
394394
@@ -480,8 +480,14 @@ export function Files() {
480480 if ( justCreatedFileIdRef . current && ! isJustCreated ) {
481481 justCreatedFileIdRef . current = null
482482 }
483- setShowPreview ( ! isJustCreated )
484- } , [ selectedFileId ] )
483+ if ( isJustCreated ) {
484+ setPreviewMode ( 'editor' )
485+ } else {
486+ const file = selectedFileId ? files . find ( ( f ) => f . id === selectedFileId ) : null
487+ const canPreview = file ? isPreviewable ( file ) : false
488+ setPreviewMode ( canPreview ? 'preview' : 'editor' )
489+ }
490+ } , [ selectedFileId , files ] )
485491
486492 useEffect ( ( ) => {
487493 if ( ! selectedFile ) return
@@ -504,10 +510,23 @@ export function Files() {
504510 return ( ) => window . removeEventListener ( 'beforeunload' , handler )
505511 } , [ isDirty ] )
506512
513+ const handleCyclePreviewMode = useCallback ( ( ) => {
514+ setPreviewMode ( ( prev ) => {
515+ if ( prev === 'editor' ) return 'split'
516+ if ( prev === 'split' ) return 'preview'
517+ return 'editor'
518+ } )
519+ } , [ ] )
520+
521+ const handleTogglePreview = useCallback ( ( ) => {
522+ setPreviewMode ( ( prev ) => ( prev === 'preview' ? 'editor' : 'preview' ) )
523+ } , [ ] )
524+
507525 const fileActions = useMemo < HeaderAction [ ] > ( ( ) => {
508526 if ( ! selectedFile ) return [ ]
509527 const canEditText = isTextEditable ( selectedFile )
510528 const canPreview = isPreviewable ( selectedFile )
529+ const hasSplitView = canEditText && canPreview
511530
512531 const saveLabel =
513532 saveStatus === 'saving'
@@ -518,16 +537,12 @@ export function Files() {
518537 ? 'Save failed'
519538 : 'Save'
520539
540+ const nextModeLabel =
541+ previewMode === 'editor' ? 'Split' : previewMode === 'split' ? 'Preview' : 'Edit'
542+ const nextModeIcon =
543+ previewMode === 'editor' ? Columns2 : previewMode === 'split' ? Eye : Pencil
544+
521545 return [
522- ...( canPreview
523- ? [
524- {
525- label : showPreview ? 'Edit' : 'Preview' ,
526- icon : showPreview ? Pencil : Eye ,
527- onClick : handleTogglePreview ,
528- } ,
529- ]
530- : [ ] ) ,
531546 ...( canEditText
532547 ? [
533548 {
@@ -540,6 +555,23 @@ export function Files() {
540555 } ,
541556 ]
542557 : [ ] ) ,
558+ ...( hasSplitView
559+ ? [
560+ {
561+ label : nextModeLabel ,
562+ icon : nextModeIcon ,
563+ onClick : handleCyclePreviewMode ,
564+ } ,
565+ ]
566+ : canPreview
567+ ? [
568+ {
569+ label : previewMode === 'preview' ? 'Edit' : 'Preview' ,
570+ icon : previewMode === 'preview' ? Pencil : Eye ,
571+ onClick : handleTogglePreview ,
572+ } ,
573+ ]
574+ : [ ] ) ,
543575 {
544576 label : 'Download' ,
545577 icon : Download ,
@@ -554,7 +586,8 @@ export function Files() {
554586 } , [
555587 selectedFile ,
556588 saveStatus ,
557- showPreview ,
589+ previewMode ,
590+ handleCyclePreviewMode ,
558591 handleTogglePreview ,
559592 handleSave ,
560593 isDirty ,
@@ -580,8 +613,6 @@ export function Files() {
580613 }
581614
582615 if ( selectedFile ) {
583- const canPreview = isPreviewable ( selectedFile )
584-
585616 return (
586617 < >
587618 < div className = 'flex h-full flex-1 flex-col overflow-hidden bg-[var(--bg)]' >
@@ -595,7 +626,7 @@ export function Files() {
595626 file = { selectedFile }
596627 workspaceId = { workspaceId }
597628 canEdit = { userPermissions . canEdit === true }
598- showPreview = { showPreview && canPreview }
629+ previewMode = { previewMode }
599630 autoFocus = { justCreatedFileIdRef . current === selectedFile . id }
600631 onDirtyChange = { setIsDirty }
601632 onSaveStatusChange = { setSaveStatus }
0 commit comments