Skip to content

Commit ac4803d

Browse files
authored
Merge pull request #18 from DeepFundAI/ls-dev
Ls dev
2 parents 4597691 + cfabbee commit ac4803d

40 files changed

+839
-2227
lines changed

electron/main/index.ts

Lines changed: 85 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -37,48 +37,54 @@ console.log("main: isDev:", isDev);
3737
console.log("NODE_ENV:", global.process.env.NODE_ENV);
3838
console.log("isPackaged:", app.isPackaged);
3939

40-
// Log unhandled errors
41-
process.on("uncaughtException", async (error) => {
42-
console.log("Uncaught Exception:", error);
40+
// Log unhandled errors for debugging
41+
process.on("uncaughtException", (error) => {
42+
console.error("Uncaught Exception:", error);
4343
});
4444

45-
process.on("unhandledRejection", async (error) => {
46-
console.log("Unhandled Rejection:", error);
45+
process.on("unhandledRejection", (error) => {
46+
console.error("Unhandled Rejection:", error);
4747
});
4848

49+
// Configure custom app paths if APP_PATH_ROOT is specified
4950
(() => {
50-
const root =
51-
global.process.env.APP_PATH_ROOT ?? import.meta.env.VITE_APP_PATH_ROOT;
51+
const root = global.process.env.APP_PATH_ROOT ?? import.meta.env.VITE_APP_PATH_ROOT;
5252

53-
if (root === undefined) {
54-
console.log(
55-
"no given APP_PATH_ROOT or VITE_APP_PATH_ROOT. default path is used."
56-
);
53+
if (!root) {
54+
console.log("No APP_PATH_ROOT or VITE_APP_PATH_ROOT specified, using default paths");
5755
return;
5856
}
5957

6058
if (!path.isAbsolute(root)) {
61-
console.log("APP_PATH_ROOT must be absolute path.");
59+
console.error("APP_PATH_ROOT must be an absolute path");
6260
global.process.exit(1);
6361
}
6462

65-
console.log(`APP_PATH_ROOT: ${root}`);
63+
console.log(`Configuring custom APP_PATH_ROOT: ${root}`);
6664

6765
const subdirName = pkg.name;
6866

69-
for (const [key, val] of [
67+
// Set app paths
68+
const pathConfigs: Array<[Parameters<typeof app.setPath>[0], string]> = [
7069
["appData", ""],
7170
["userData", subdirName],
7271
["sessionData", subdirName],
73-
] as const) {
72+
];
73+
74+
pathConfigs.forEach(([key, val]) => {
7475
app.setPath(key, path.join(root, val));
75-
}
76+
});
7677

7778
app.setAppLogsPath(path.join(root, subdirName, "Logs"));
7879
})();
7980

8081
console.log("appPath:", app.getAppPath());
8182

83+
const pathKeys: Array<Parameters<typeof app.getPath>[0]> = [
84+
"home", "appData", "userData", "sessionData", "logs", "temp"
85+
];
86+
pathKeys.forEach((key) => console.log(`${key}:`, app.getPath(key)));
87+
8288
// Register custom protocol scheme before app ready
8389
protocol.registerSchemesAsPrivileged([
8490
{
@@ -93,16 +99,6 @@ protocol.registerSchemesAsPrivileged([
9399
}
94100
]);
95101

96-
const keys: Parameters<typeof app.getPath>[number][] = [
97-
"home",
98-
"appData",
99-
"userData",
100-
"sessionData",
101-
"logs",
102-
"temp",
103-
];
104-
keys.forEach((key) => console.log(`${key}:`, app.getPath(key)));
105-
106102
// Initialize server manager
107103
const serverManager = new ServerManager();
108104

@@ -123,80 +119,17 @@ let ekoService: EkoService;
123119
let mainWindowManager: MainWindowManager;
124120

125121
/**
126-
* Initialize main window and all related components
127-
* Including: detailView, ekoService, windowContext registration
122+
* Setup main window close event handler
123+
* Handles task termination and window hiding/closing based on platform
128124
*/
129-
async function initializeMainWindow(): Promise<BrowserWindow> {
130-
console.log('[Main] Starting main window initialization...');
131-
132-
// Create main window (includes transition page and service waiting logic)
133-
mainWindow = await mainWindowManager.createMainWindow();
134-
135-
mainWindow.contentView.setBounds({
136-
x: 0,
137-
y: 0,
138-
width: mainWindow.getBounds().width,
139-
height: mainWindow.getBounds().height,
140-
});
141-
142-
// Create detail panel area
143-
detailView = createView(`https://www.google.com`, "view", '1');
144-
mainWindow.contentView.addChildView(detailView);
145-
detailView.setBounds({
146-
x: 818,
147-
y: 264,
148-
width: 748,
149-
height: 560,
150-
});
151-
152-
// Set detail view hidden by default
153-
detailView.setVisible(false);
154-
155-
detailView.webContents.setWindowOpenHandler(({url}) => {
156-
detailView.webContents.loadURL(url);
157-
return {
158-
action: "deny",
159-
}
160-
})
161-
162-
// Listen for detail view URL changes
163-
detailView.webContents.on('did-navigate', (_event, url) => {
164-
console.log('detail view did-navigate:', url);
165-
mainWindow?.webContents.send('url-changed', url);
166-
});
167-
168-
detailView.webContents.on('did-navigate-in-page', (_event, url) => {
169-
console.log('detail view did-navigate-in-page:', url);
170-
mainWindow?.webContents.send('url-changed', url);
171-
});
172-
173-
// Initialize EkoService
174-
ekoService = new EkoService(mainWindow, detailView);
175-
176-
// Register main window to windowContextManager
177-
const mainWindowContext: WindowContext = {
178-
window: mainWindow,
179-
detailView,
180-
historyView,
181-
ekoService,
182-
webContentsId: mainWindow.webContents.id,
183-
windowType: 'main'
184-
};
185-
windowContextManager.registerWindow(mainWindowContext);
186-
console.log('[Main] Main window registered to WindowContextManager');
187-
188-
// Listen for window close event (close: triggered before closing, can be prevented)
189-
// Unified handling for Mac and Windows: check task status, prompt user
190-
mainWindow.on('close', async (event) => {
191-
// Check if any task is running
192-
const hasRunningTask = ekoService.hasRunningTask();
125+
function setupMainWindowCloseHandler(window: BrowserWindow, service: EkoService): void {
126+
window.on('close', async (event) => {
127+
const hasRunningTask = service.hasRunningTask();
193128

194129
if (hasRunningTask) {
195-
// Prevent default close behavior
196130
event.preventDefault();
197131

198-
// Show confirmation dialog
199-
const { response } = await dialog.showMessageBox(mainWindow, {
132+
const { response } = await dialog.showMessageBox(window, {
200133
type: 'warning',
201134
title: 'Task Running',
202135
message: 'A task is currently running. Closing the window will cause the task to fail',
@@ -209,108 +142,108 @@ async function initializeMainWindow(): Promise<BrowserWindow> {
209142
});
210143

211144
if (response === 1) {
212-
// Stop task
213-
console.log('[Main] User chose to stop task');
214-
215-
// Get all task IDs
216-
const allTaskIds = ekoService['eko']?.getAllTaskId() || [];
145+
const allTaskIds = service['eko']?.getAllTaskId() || [];
146+
await service.abortAllTasks();
217147

218-
// Abort all tasks
219-
await ekoService.abortAllTasks();
220-
221-
// Send abort event (frontend will listen and update IndexedDB)
222148
allTaskIds.forEach(taskId => {
223-
mainWindow.webContents.send('task-aborted-by-system', {
149+
window.webContents.send('task-aborted-by-system', {
224150
taskId,
225151
reason: 'User closed window, task terminated',
226152
timestamp: new Date().toISOString()
227153
});
228154
});
229155

230-
// Delay to ensure message delivery and processing
231156
await new Promise(resolve => setTimeout(resolve, 1000));
232157

233-
if (process.platform === 'darwin') {
234-
// Mac: actually close window
235-
mainWindow.destroy();
236-
} else {
237-
// Windows/Linux: hide window
238-
mainWindow.hide();
239-
}
240-
}
241-
// response === 0: cancel close, do nothing
242-
} else {
243-
// No task running
244-
if (process.platform !== 'darwin') {
245-
// Windows/Linux: hide to tray
246-
event.preventDefault();
247-
mainWindow.hide();
248-
console.log('[Main] Main window hidden to tray');
158+
process.platform === 'darwin' ? window.destroy() : window.hide();
249159
}
250-
// Mac: use default behavior (close window but keep app running)
160+
} else if (process.platform !== 'darwin') {
161+
event.preventDefault();
162+
window.hide();
251163
}
252164
});
165+
}
166+
167+
/**
168+
* Initialize main window and all related components
169+
* Including: detailView, ekoService, windowContext registration
170+
*/
171+
async function initializeMainWindow(): Promise<BrowserWindow> {
172+
mainWindow = await mainWindowManager.createMainWindow();
173+
174+
const windowBounds = mainWindow.getBounds();
175+
mainWindow.contentView.setBounds({
176+
x: 0,
177+
y: 0,
178+
width: windowBounds.width,
179+
height: windowBounds.height,
180+
});
181+
182+
detailView = createView(`https://www.google.com`, "view", '1');
183+
mainWindow.contentView.addChildView(detailView);
184+
detailView.setBounds({ x: 818, y: 264, width: 748, height: 560 });
185+
detailView.setVisible(false);
186+
187+
detailView.webContents.setWindowOpenHandler(({ url }) => {
188+
detailView.webContents.loadURL(url);
189+
return { action: "deny" };
190+
});
191+
192+
const handleUrlChange = (_event: any, url: string) => {
193+
mainWindow?.webContents.send('url-changed', url);
194+
};
195+
196+
detailView.webContents.on('did-navigate', handleUrlChange);
197+
detailView.webContents.on('did-navigate-in-page', handleUrlChange);
198+
199+
ekoService = new EkoService(mainWindow, detailView);
200+
201+
windowContextManager.registerWindow({
202+
window: mainWindow,
203+
detailView,
204+
historyView,
205+
ekoService,
206+
webContentsId: mainWindow.webContents.id,
207+
windowType: 'main'
208+
});
209+
210+
setupMainWindowCloseHandler(mainWindow, ekoService);
253211

254-
// Listen for window closed event (closed: triggered after window is closed)
255-
// Clean up context
256212
mainWindow.on('closed', () => {
257-
console.log('[Main] Main window closed, cleaning up context');
258213
try {
259214
if (mainWindow && !mainWindow.isDestroyed() && mainWindow.webContents) {
260215
windowContextManager.unregisterWindow(mainWindow.webContents.id);
261216
}
262217
} catch (error) {
263-
console.error('[Main] Failed to clean up main window context:', error);
218+
console.error('[Main] Failed to clean up window context:', error);
264219
}
265220
});
266221

267-
console.log('[Main] Main window initialization completed');
268222
return mainWindow;
269223
}
270224

271225
(async () => {
272226
await app.whenReady();
273-
console.log("App is ready");
274227

275-
// Register global client protocol
276228
registerClientProtocol(protocol);
277229

278230
if (isDev) {
279-
const iconPath = path.join(cwd(), "assets/icons/logo.png");
280-
console.log("Setting app icon:", iconPath);
281-
app.dock?.setIcon(iconPath);
231+
app.dock?.setIcon(path.join(cwd(), "assets/icons/logo.png"));
282232
}
283233

284-
// Load any existing cookies from ElectronStore, set as cookie
285234
await initCookies();
286235

287-
// Initialize main window manager
288236
mainWindowManager = new MainWindowManager(serverManager);
289-
290-
// Initialize main window and all related components
291237
mainWindow = await initializeMainWindow();
292238

293-
// Create system tray
294239
createTray(mainWindow);
295-
console.log('[Main] System tray created');
296-
297-
// Start task scheduler
298240
taskScheduler.start();
299-
console.log('[Main] TaskScheduler started');
300241

301-
// macOS activate event handler
302242
app.on("activate", async () => {
303-
// Check if main window exists (regardless of task windows)
304-
const hasMainWindow = mainWindow && !mainWindow.isDestroyed();
305-
306-
if (!hasMainWindow) {
307-
// Create main window if it doesn't exist (even if task windows exist)
308-
console.log('[Main] App activated, main window does not exist, creating main window');
243+
if (!mainWindow || mainWindow.isDestroyed()) {
309244
mainWindow = await initializeMainWindow();
310245
setupMenu(mainWindow);
311246
} else {
312-
// Main window exists, show and focus
313-
console.log('[Main] App activated, main window exists, showing and focusing');
314247
mainWindow.show();
315248
mainWindow.focus();
316249
}
@@ -319,16 +252,9 @@ async function initializeMainWindow(): Promise<BrowserWindow> {
319252
return mainWindow;
320253
})().then((win) => setupMenu(win));
321254

322-
// Don't quit app when all windows are closed, keep running in background (for scheduled tasks)
323-
// User needs to use "Quit" option in tray menu to actually quit the app
324255
app.on("window-all-closed", () => {
325-
console.log('[Main] All windows closed, app continues running in background');
326-
// Don't call app.quit(), let app continue running
327-
// Scheduled tasks will continue executing in background
256+
// Keep app running in background for scheduled tasks
328257
});
329258

330-
// Register all IPC handlers
331259
registerAllIpcHandlers();
332-
333260
reloadOnChange();
334-
// setupAutoUpdater();

0 commit comments

Comments
 (0)