@@ -867,7 +867,7 @@ function executePendingAction() {
867867
868868// --- In-memory file cache (lives for the session, cleared on workspace change) ---
869869// Updated only on first fetch and on save — never by polling.
870- interface CachedFile { code: string ; language: string }
870+ interface CachedFile { code: string ; language: string ; mtime : number }
871871const fileCache = new Map <string , CachedFile >();
872872
873873// --- Hot-reload: mtime polling for open panes only (1s) ---
@@ -924,14 +924,30 @@ async function loadFileIntoPane(paneId: string, path: string) {
924924 pane .filePath = path ;
925925 pane .language = detectLanguage (path );
926926
927- // Serve from cache — same code path as a fresh fetch (no visual difference)
927+ // Serve from cache instantly, then refresh from disk in background
928928 const cached = fileCache .get (path );
929929 if (cached ) {
930930 pane .code = cached .code ;
931931 pane .savedCode = cached .code ;
932932 pane .language = cached .language ;
933- fetchMtime (path ).then (mt => { if (mt !== null ) lastMtime .set (paneId , mt ); });
934933 saveWorkspaceConfig ();
934+ // Background: check mtime, only fetch full file if changed on disk
935+ fetchMtime (path ).then (async (mt ) => {
936+ if (mt !== null ) lastMtime .set (paneId , mt );
937+ if (mt === null || mt <= cached .mtime ) return ; // unchanged
938+ try {
939+ const res = await apiFetch (" /read?path=" + encodeURIComponent (path ));
940+ if (! res .ok ) return ;
941+ const text = await res .text ();
942+ fileCache .set (path , { code: text , language: pane .language , mtime: mt });
943+ // Only update pane if user hasn't edited since
944+ if (pane .code === cached .code ) {
945+ userEdited .delete (paneId );
946+ pane .code = text ;
947+ pane .savedCode = text ;
948+ }
949+ } catch {}
950+ });
935951 return ;
936952 }
937953
@@ -948,16 +964,22 @@ async function loadFileIntoPane(paneId: string, path: string) {
948964 const text = await res .text ();
949965 pane .code = text ;
950966 pane .savedCode = text ;
951- // Cache on first fetch
952- fileCache .set (path , { code: text , language: pane .language });
967+ // Cache on first fetch (mtime filled async below)
968+ fileCache .set (path , { code: text , language: pane .language , mtime: 0 });
953969 } catch {
954970 pane .code = " Network error: unable to load file" ;
955971 pane .savedCode = pane .code ;
956972 pane .language = " plaintext" ;
957973 } finally {
958974 loadingPaneId .value = null ;
959975 }
960- fetchMtime (path ).then (mt => { if (mt !== null ) lastMtime .set (paneId , mt ); });
976+ fetchMtime (path ).then (mt => {
977+ if (mt !== null ) {
978+ lastMtime .set (paneId , mt );
979+ const c = fileCache .get (path );
980+ if (c ) c .mtime = mt ;
981+ }
982+ });
961983 saveWorkspaceConfig ();
962984}
963985
@@ -978,8 +1000,11 @@ async function savePaneFile(paneId: string) {
9781000 } else {
9791001 pane .savedCode = pane .code ;
9801002 const filePath = pane .filePath ;
981- fileCache .set (filePath , { code: pane .code , language: pane .language });
982- fetchMtime (filePath ).then (mt => { if (mt !== null ) lastMtime .set (paneId , mt ); });
1003+ fetchMtime (filePath ).then (mt => {
1004+ const mtime = mt ?? Date .now ();
1005+ fileCache .set (filePath , { code: pane .code , language: pane .language , mtime });
1006+ if (mt !== null ) lastMtime .set (paneId , mtime );
1007+ });
9831008 }
9841009 } catch {
9851010 console .error (" Network error: unable to save file" );
0 commit comments