@@ -4,7 +4,7 @@ import path from 'node:path'
44import os , { homedir } from 'node:os'
55import log from 'electron-log'
66import { update , registerUpdateIpcHandlers } from './update'
7- import { checkToolInstalled , installDependencies , killProcessOnPort , startBackend } from './init'
7+ import { checkToolInstalled , killProcessOnPort , startBackend } from './init'
88import { WebViewManager } from './webview'
99import { FileReader } from './fileReader'
1010import { ChildProcessWithoutNullStreams } from 'node:child_process'
@@ -18,9 +18,9 @@ import kill from 'tree-kill';
1818import { zipFolder } from './utils/log'
1919import axios from 'axios' ;
2020import FormData from 'form-data' ;
21+ import { checkAndInstallDepsOnUpdate , PromiseReturnType , getInstallationStatus } from './install-deps'
2122
2223const userData = app . getPath ( 'userData' ) ;
23- const versionFile = path . join ( userData , 'version.txt' ) ;
2424
2525// ==================== constants ====================
2626const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) ) ;
@@ -50,69 +50,6 @@ findAvailablePort(browser_port).then(port => {
5050 app . commandLine . appendSwitch ( 'remote-debugging-port' , port + '' ) ;
5151} ) ;
5252
53- // Read last run version and install dependencies on update
54- async function checkAndInstallDepsOnUpdate ( ) : Promise < boolean > {
55- const currentVersion = app . getVersion ( ) ;
56- return new Promise ( async ( resolve , reject ) => {
57- try {
58- log . info ( ' start check version' , { currentVersion } ) ;
59-
60- // Check if version file exists
61- const versionExists = fs . existsSync ( versionFile ) ;
62- let savedVersion = '' ;
63-
64- if ( versionExists ) {
65- savedVersion = fs . readFileSync ( versionFile , 'utf-8' ) . trim ( ) ;
66- log . info ( ' read saved version' , { savedVersion } ) ;
67- } else {
68- log . info ( ' version file not exist, will create new file' ) ;
69- }
70-
71- // If version file does not exist or version does not match, reinstall dependencies
72- if ( ! versionExists || savedVersion !== currentVersion ) {
73- log . info ( ' version changed, prepare to reinstall uv dependencies...' , {
74- currentVersion,
75- savedVersion : versionExists ? savedVersion : 'none' ,
76- reason : ! versionExists ? 'version file not exist' : 'version not match'
77- } ) ;
78-
79- // Notify frontend to update
80- if ( win && ! win . isDestroyed ( ) ) {
81- win . webContents . send ( 'update-notification' , {
82- type : 'version-update' ,
83- currentVersion,
84- previousVersion : versionExists ? savedVersion : 'none' ,
85- reason : ! versionExists ? 'version file not exist' : 'version not match'
86- } ) ;
87- }
88-
89- // Update version file
90- fs . writeFileSync ( versionFile , currentVersion ) ;
91- log . info ( ' version file updated' , { currentVersion } ) ;
92-
93- // Install dependencies
94- const result = await installDependencies ( ) ;
95- if ( ! result ) {
96- log . error ( ' install dependencies failed' ) ;
97- resolve ( false ) ;
98- return
99- }
100- resolve ( true ) ;
101- log . info ( ' install dependencies complete' ) ;
102- return
103- } else {
104- log . info ( ' version not changed, skip install dependencies' , { currentVersion } ) ;
105- resolve ( true ) ;
106- return
107- }
108- } catch ( error ) {
109- log . error ( ' check version and install dependencies error:' , error ) ;
110- resolve ( false ) ;
111- return
112- }
113- } )
114- }
115-
11653// ==================== app config ====================
11754process . env . APP_ROOT = MAIN_DIST ;
11855process . env . VITE_PUBLIC = VITE_PUBLIC ;
@@ -259,51 +196,6 @@ const checkManagerInstance = (manager: any, name: string) => {
259196 return manager ;
260197} ;
261198
262- export const handleDependencyInstallation = async ( ) => {
263- try {
264- log . info ( ' start install dependencies...' ) ;
265-
266- const isSuccess = await installDependencies ( ) ;
267- if ( ! isSuccess ) {
268- log . error ( ' install dependencies failed' ) ;
269- return { success : false , error : 'install dependencies failed' } ;
270- }
271-
272- log . info ( ' install dependencies success, check tool installed status...' ) ;
273- const isToolInstalled = await checkToolInstalled ( ) ;
274- log . info ( 'isToolInstalled && !python_process' , isToolInstalled && ! python_process ) ;
275- if ( isToolInstalled && ! python_process ) {
276- log . info ( ' tool installed, start backend service...' ) ;
277- python_process = await startBackend ( ( port ) => {
278- backendPort = port ;
279- log . info ( ' backend service start success' , { port } ) ;
280- } ) ;
281-
282- // Notify frontend to install success
283- if ( win && ! win . isDestroyed ( ) ) {
284- win . webContents . send ( 'install-dependencies-complete' , { success : true , code : 0 } ) ;
285- }
286-
287- python_process ?. on ( 'exit' , ( code , signal ) => {
288- log . info ( ' python process exit' , { code, signal } ) ;
289- } ) ;
290- } else if ( ! isToolInstalled ) {
291- log . warn ( ' tool not installed, skip backend start' ) ;
292- } else {
293- log . info ( ' backend process already exist, skip start' ) ;
294- }
295-
296- log . info ( ' install dependencies complete' ) ;
297- return { success : true } ;
298- } catch ( error : any ) {
299- log . error ( ' install dependencies error:' , error ) ;
300- if ( win && ! win . isDestroyed ( ) ) {
301- win . webContents . send ( 'install-dependencies-complete' , { success : false , code : 2 } ) ;
302- }
303- return { success : false , error : error . message } ;
304- }
305- } ;
306-
307199function registerIpcHandlers ( ) {
308200 // ==================== basic info handler ====================
309201 ipcMain . handle ( 'get-browser-port' , ( ) => {
@@ -934,13 +826,35 @@ function registerIpcHandlers() {
934826 } ) ;
935827
936828 // ==================== dependency install handler ====================
937- ipcMain . handle ( 'install-dependencies' , handleDependencyInstallation ) ;
938- ipcMain . handle ( 'frontend-ready' , handleDependencyInstallation ) ;
829+ ipcMain . handle ( 'install-dependencies' , async ( ) => {
830+ try {
831+ if ( win === null ) throw new Error ( "Window is null" ) ;
832+ //Force installation even if versionFile exists
833+ const isInstalled = await checkAndInstallDepsOnUpdate ( { win, forceInstall : true } ) ;
834+ return { success : true , isInstalled } ;
835+ } catch ( error ) {
836+ return { success : false , error : ( error as Error ) . message } ;
837+ }
838+ } ) ;
939839
940840 ipcMain . handle ( 'check-tool-installed' , async ( ) => {
941841 try {
942842 const isInstalled = await checkToolInstalled ( ) ;
943- return { success : true , isInstalled } ;
843+ return { success : true , isInstalled : isInstalled . success } ;
844+ } catch ( error ) {
845+ return { success : false , error : ( error as Error ) . message } ;
846+ }
847+ } ) ;
848+
849+ ipcMain . handle ( 'get-installation-status' , async ( ) => {
850+ try {
851+ const { isInstalling, hasLockFile } = await getInstallationStatus ( ) ;
852+ return {
853+ success : true ,
854+ isInstalling,
855+ hasLockFile,
856+ timestamp : Date . now ( )
857+ } ;
944858 } catch ( error ) {
945859 return { success : false , error : ( error as Error ) . message } ;
946860 }
@@ -1006,12 +920,13 @@ async function createWindow() {
1006920 update ( win ) ;
1007921
1008922 // ==================== check tool installed ====================
1009- let res = await checkAndInstallDepsOnUpdate ( ) ;
1010- if ( ! res ) {
1011- log . info ( 'checkAndInstallDepsOnUpdate,install dependencies failed' ) ;
1012- win . webContents . send ( 'install-dependencies-complete' , { success : false , code : 2 } ) ;
923+ let res : PromiseReturnType = await checkAndInstallDepsOnUpdate ( { win } ) ;
924+ if ( ! res . success ) {
925+ log . info ( "[DEPS INSTALL] Dependency Error: " , res . message ) ;
926+ win . webContents . send ( 'install-dependencies-complete' , { success : false , code : 2 , error : res . message } ) ;
1013927 return ;
1014- }
928+ }
929+ log . info ( "[DEPS INSTALL] Dependency Success: " , res . message ) ;
1015930 await checkAndStartBackend ( ) ;
1016931}
1017932
@@ -1069,27 +984,30 @@ const setupExternalLinkHandling = () => {
1069984// ==================== check and start backend ====================
1070985const checkAndStartBackend = async ( ) => {
1071986 log . info ( 'Checking and starting backend service...' ) ;
987+ try {
988+ const isToolInstalled = await checkToolInstalled ( ) ;
989+ if ( isToolInstalled . success ) {
990+ log . info ( 'Tool installed, starting backend service...' ) ;
1072991
1073- const isToolInstalled = await checkToolInstalled ( ) ;
1074- if ( isToolInstalled ) {
1075- log . info ( 'Tool installed, starting backend service...' ) ;
1076-
1077- // Notify frontend installation success
1078- if ( win && ! win . isDestroyed ( ) ) {
1079- win . webContents . send ( 'install-dependencies-complete' , { success : true , code : 0 } ) ;
1080- }
992+ // Notify frontend installation success
993+ if ( win && ! win . isDestroyed ( ) ) {
994+ win . webContents . send ( 'install-dependencies-complete' , { success : true , code : 0 } ) ;
995+ }
1081996
1082- python_process = await startBackend ( ( port ) => {
1083- backendPort = port ;
1084- log . info ( 'Backend service started successfully' , { port } ) ;
1085- } ) ;
997+ python_process = await startBackend ( ( port ) => {
998+ backendPort = port ;
999+ log . info ( 'Backend service started successfully' , { port } ) ;
1000+ } ) ;
10861001
1087- python_process ?. on ( 'exit' , ( code , signal ) => {
1002+ python_process ?. on ( 'exit' , ( code , signal ) => {
10881003
1089- log . info ( 'Python process exited' , { code, signal } ) ;
1090- } ) ;
1091- } else {
1092- log . warn ( 'Tool not installed, cannot start backend service' ) ;
1004+ log . info ( 'Python process exited' , { code, signal } ) ;
1005+ } ) ;
1006+ } else {
1007+ log . warn ( 'Tool not installed, cannot start backend service' ) ;
1008+ }
1009+ } catch ( error ) {
1010+ log . debug ( "Cannot Start Backend due to " , error )
10931011 }
10941012} ;
10951013
0 commit comments