Skip to content

Commit 5588eca

Browse files
authored
Fix #352 install enhanced (#404)
2 parents 3ff45dc + b477363 commit 5588eca

File tree

11 files changed

+942
-508
lines changed

11 files changed

+942
-508
lines changed

electron/main/index.ts

Lines changed: 53 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import path from 'node:path'
44
import os, { homedir } from 'node:os'
55
import log from 'electron-log'
66
import { update, registerUpdateIpcHandlers } from './update'
7-
import { checkToolInstalled, installDependencies, killProcessOnPort, startBackend } from './init'
7+
import { checkToolInstalled, killProcessOnPort, startBackend } from './init'
88
import { WebViewManager } from './webview'
99
import { FileReader } from './fileReader'
1010
import { ChildProcessWithoutNullStreams } from 'node:child_process'
@@ -18,9 +18,9 @@ import kill from 'tree-kill';
1818
import { zipFolder } from './utils/log'
1919
import axios from 'axios';
2020
import FormData from 'form-data';
21+
import { checkAndInstallDepsOnUpdate, PromiseReturnType, getInstallationStatus } from './install-deps'
2122

2223
const userData = app.getPath('userData');
23-
const versionFile = path.join(userData, 'version.txt');
2424

2525
// ==================== constants ====================
2626
const __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 ====================
11754
process.env.APP_ROOT = MAIN_DIST;
11855
process.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-
307199
function 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 ====================
1070985
const 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

Comments
 (0)