11import Splitter , { GutterTheme , SplitDirection } from "@devbookhq/splitter" ;
22import Tile from "../components/Tiles/Tile" ;
33import FileExplorer from "../components/Tiles/FileExplorer" ;
4- import { useCallback , useContext , useEffect , useState } from "react" ;
4+ import { useCallback , useContext , useEffect , useRef , useState } from "react" ;
55import Editor from "../components/Tiles/Editor" ;
66import MenuBar from "../components/Menu/MenuBar" ;
77import "./IDE.css" ;
@@ -11,6 +11,7 @@ import { useIDE } from "../utilities/IDEContext";
1111import { registerFileSystemOverlay } from "@codingame/monaco-vscode-files-service-override" ;
1212import TauriFileSystemProvider from "../utilities/TauriFileSystemProvider" ;
1313import { invoke } from "@tauri-apps/api/core" ;
14+ import { path } from "@tauri-apps/api" ;
1415import {
1516 Button ,
1617 Divider ,
@@ -25,6 +26,7 @@ import { restartServer } from "../utilities/lsp-client";
2526import BottomBar from "../components/Tiles/BottomBar" ;
2627import { open as openFileDialog } from "@tauri-apps/plugin-dialog" ;
2728import { IStandaloneCodeEditor } from "@codingame/monaco-vscode-api/vscode/vs/editor/standalone/browser/standaloneCodeEditor" ;
29+ import { readTextFile , writeTextFile } from "@tauri-apps/plugin-fs" ;
2830
2931export interface IDEProps { }
3032
@@ -45,7 +47,7 @@ export default () => {
4547 const [ undo , setUndo ] = useState < ( ( ) => void ) | null > ( null ) ;
4648 const [ redo , setRedo ] = useState < ( ( ) => void ) | null > ( null ) ;
4749 const [ theme ] = useStore < "light" | "dark" > ( "appearance/theme" , "dark" ) ;
48- const { path } = useParams < "path" > ( ) ;
50+ const { path : filePath } = useParams < "path" > ( ) ;
4951 const { openFolderDialog, selectedToolchain, hasLimitedRam, initialized } =
5052 useIDE ( ) ;
5153 const [ sourcekitStartup , setSourcekitStartup ] = useStore < boolean | null > (
@@ -57,7 +59,7 @@ export default () => {
5759 false
5860 ) ;
5961
60- if ( ! path ) {
62+ if ( ! filePath ) {
6163 throw new Error ( "Path parameter is required in IDE component" ) ;
6264 }
6365
@@ -68,35 +70,73 @@ export default () => {
6870 const [ editor , setEditor ] = useState < IStandaloneCodeEditor | null > ( null ) ;
6971 const { addToast } = useToast ( ) ;
7072
73+ const hasAttemptedToReadOpenFiles = useRef < string | null > ( null ) ;
74+
75+ useEffect ( ( ) => {
76+ ( async ( ) => {
77+ if ( ! filePath ) return ;
78+ const savePath = await path . join (
79+ filePath ,
80+ ".crosscode" ,
81+ "openFiles.json"
82+ ) ;
83+ try {
84+ let text = await readTextFile ( savePath ) ;
85+ console . log ( text ) ;
86+ if ( ! text ) return ;
87+ let files = JSON . parse ( text ) as string [ ] ;
88+ setOpenFiles ( files ) ;
89+ } catch ( e ) {
90+ void e ;
91+ } finally {
92+ hasAttemptedToReadOpenFiles . current = filePath ;
93+ }
94+ } ) ( ) ;
95+ } , [ filePath ] ) ;
96+
97+ useEffect ( ( ) => {
98+ ( async ( ) => {
99+ if ( ! filePath || hasAttemptedToReadOpenFiles . current !== filePath ) return ;
100+ const savePath = await path . join (
101+ filePath ,
102+ ".crosscode" ,
103+ "openFiles.json"
104+ ) ;
105+ writeTextFile ( savePath , JSON . stringify ( openFiles ) ) . catch ( ( err ) => {
106+ console . error ( "Error writing openFiles.json:" , err ) ;
107+ } ) ;
108+ } ) ( ) ;
109+ } , [ openFiles , filePath ] ) ;
110+
71111 useEffect ( ( ) => {
72112 ( async ( ) => {
73- if ( ! store || ! storeInitialized || ! path ) return ;
74- await store . set ( "last-opened-project" , encodeURIComponent ( path ! ) ) ;
113+ if ( ! store || ! storeInitialized || ! filePath ) return ;
114+ await store . set ( "last-opened-project" , encodeURIComponent ( filePath ! ) ) ;
75115 } ) ( ) ;
76- } , [ path , store , storeInitialized ] ) ;
116+ } , [ filePath , store , storeInitialized ] ) ;
77117
78118 useEffect ( ( ) => {
79119 if (
80- path === undefined ||
81- path === null ||
120+ filePath === undefined ||
121+ filePath === null ||
82122 selectedToolchain === null ||
83123 ! initialized
84124 )
85125 return ;
86126 setProjectValidation ( null ) ;
87127 ( async ( ) => {
88- if ( path ) {
128+ if ( filePath ) {
89129 const toolchainPath = selectedToolchain ?. path ?? "" ;
90130 const validation = await invoke < ProjectValidation > ( "validate_project" , {
91- projectPath : path ,
131+ projectPath : filePath ,
92132 toolchainPath : toolchainPath ,
93133 } ) ;
94134 if ( validation ) {
95135 setProjectValidation ( validation ) ;
96136 }
97137 }
98138 } ) ( ) ;
99- } , [ path , selectedToolchain , initialized ] ) ;
139+ } , [ filePath , selectedToolchain , initialized ] ) ;
100140
101141 useEffect ( ( ) => {
102142 if ( openFiles . length === 0 ) {
@@ -110,7 +150,7 @@ export default () => {
110150 useEffect ( ( ) => {
111151 let dispose = ( ) => { } ;
112152
113- if ( path ) {
153+ if ( filePath ) {
114154 const provider = new TauriFileSystemProvider ( false ) ;
115155 const overlayDisposable = registerFileSystemOverlay ( 1 , provider ) ;
116156 dispose = ( ) => {
@@ -121,7 +161,7 @@ export default () => {
121161 return ( ) => {
122162 dispose ( ) ;
123163 } ;
124- } , [ path ] ) ;
164+ } , [ filePath ] ) ;
125165
126166 useEffect ( ( ) => {
127167 let autoEnable = async ( ) => {
@@ -136,17 +176,17 @@ export default () => {
136176 if ( ! sourcekitStartup || selectedToolchain == null ) return ;
137177 requestAnimationFrame ( async ( ) => {
138178 try {
139- if ( autoStartedLsp === path ) return ;
140- autoStartedLsp = path ;
141- await restartServer ( path , selectedToolchain ) ;
179+ if ( autoStartedLsp === filePath ) return ;
180+ autoStartedLsp = filePath ;
181+ await restartServer ( filePath , selectedToolchain ) ;
142182 } catch ( e ) {
143183 console . error ( "Failed to start SourceKit-LSP:" , e ) ;
144184 addToast . error (
145185 "Failed to start SourceKit-LSP (see devtools for details). Some language features may not be available."
146186 ) ;
147187 }
148188 } ) ;
149- } , [ sourcekitStartup , path , selectedToolchain ] ) ;
189+ } , [ sourcekitStartup , filePath , selectedToolchain ] ) ;
150190
151191 const openNewFile = useCallback ( ( file : string ) => {
152192 setOpenFile ( file ) ;
@@ -184,7 +224,7 @@ export default () => {
184224 initialSizes = { [ 20 , 80 ] }
185225 >
186226 < Tile className = "file-explorer-tile" >
187- < FileExplorer openFolder = { path } setOpenFile = { openNewFile } />
227+ < FileExplorer openFolder = { filePath } setOpenFile = { openNewFile } />
188228 </ Tile >
189229 < Splitter
190230 gutterTheme = { theme === "dark" ? GutterTheme . Dark : GutterTheme . Light }
0 commit comments