77 globalShortcut,
88 dialog,
99 shell,
10+ session,
1011} = require ( "electron" ) ;
1112let autoUpdater = null ;
1213let autoUpdaterLoadError = null ;
@@ -465,6 +466,34 @@ function getDesktopSettingsPath() {
465466 return path . join ( dir , "desktop-settings.json" ) ;
466467}
467468
469+ function getPackagedUiDir ( ) {
470+ if ( ! app . isPackaged ) return null ;
471+ try {
472+ return path . join ( process . resourcesPath , "ui" ) ;
473+ } catch {
474+ return null ;
475+ }
476+ }
477+
478+ function readPackagedUiBuildId ( ) {
479+ const uiDir = getPackagedUiDir ( ) ;
480+ if ( ! uiDir ) return "" ;
481+
482+ try {
483+ const indexPath = path . join ( uiDir , "index.html" ) ;
484+ if ( ! fs . existsSync ( indexPath ) ) return "" ;
485+ const html = fs . readFileSync ( indexPath , { encoding : "utf8" } ) ;
486+ const match =
487+ html . match ( / b u i l d I d : " ( [ ^ " ] + ) " / ) ||
488+ html . match ( / \/ _ p a y l o a d \. j s o n \? ( [ ^ " ' & < > \s ] + ) / ) ||
489+ html . match ( / d a t a - s r c = " \/ _ p a y l o a d \. j s o n \? ( [ ^ " ] + ) " / ) ;
490+ return String ( match ?. [ 1 ] || "" ) . trim ( ) ;
491+ } catch ( err ) {
492+ logMain ( `[main] failed to read packaged UI build id: ${ err ?. message || err } ` ) ;
493+ return "" ;
494+ }
495+ }
496+
468497function loadDesktopSettings ( ) {
469498 if ( desktopSettings ) return desktopSettings ;
470499
@@ -476,6 +505,9 @@ function loadDesktopSettings() {
476505 ignoredUpdateVersion : "" ,
477506 // Backend (FastAPI) listens on this port. Used in packaged builds.
478507 backendPort : DEFAULT_BACKEND_PORT ,
508+ // Tracks the packaged UI build so we can invalidate Chromium's HTTP cache
509+ // after upgrades without wiping user data/localStorage.
510+ lastSeenUiBuildId : "" ,
479511 } ;
480512
481513 const p = getDesktopSettingsPath ( ) ;
@@ -539,6 +571,33 @@ function setIgnoredUpdateVersion(version) {
539571 return desktopSettings . ignoredUpdateVersion ;
540572}
541573
574+ async function refreshRendererCacheForPackagedUi ( ) {
575+ if ( ! app . isPackaged ) return ;
576+
577+ const nextBuildId = readPackagedUiBuildId ( ) ;
578+ if ( ! nextBuildId ) return ;
579+
580+ const prevBuildId = String ( loadDesktopSettings ( ) ?. lastSeenUiBuildId || "" ) . trim ( ) ;
581+ if ( prevBuildId === nextBuildId ) return ;
582+
583+ try {
584+ const ses = session ?. defaultSession ;
585+ if ( ses ) {
586+ await ses . clearCache ( ) ;
587+ try {
588+ await ses . clearStorageData ( { storages : [ "serviceworkers" ] } ) ;
589+ } catch { }
590+ }
591+ logMain ( `[main] cleared renderer cache for UI build change: ${ prevBuildId || "(none)" } -> ${ nextBuildId } ` ) ;
592+ } catch ( err ) {
593+ logMain ( `[main] failed to clear renderer cache for UI build change: ${ err ?. message || err } ` ) ;
594+ }
595+
596+ loadDesktopSettings ( ) ;
597+ desktopSettings . lastSeenUiBuildId = nextBuildId ;
598+ persistDesktopSettings ( ) ;
599+ }
600+
542601function parseEnvBool ( value ) {
543602 if ( value == null ) return null ;
544603 const v = String ( value ) . trim ( ) . toLowerCase ( ) ;
@@ -1614,6 +1673,7 @@ function registerWindowIpc() {
16141673
16151674async function main ( ) {
16161675 await app . whenReady ( ) ;
1676+ await refreshRendererCacheForPackagedUi ( ) ;
16171677 Menu . setApplicationMenu ( null ) ;
16181678 registerWindowIpc ( ) ;
16191679 registerDebugShortcuts ( ) ;
0 commit comments