experiments in a post-browser web
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor(electron): delete legacy handlers + datastore-viewer tile-preload (Phase 3.11b partial)

+28 -112
+21 -105
backend/electron/ipc.ts
··· 5 5 * Handlers are thin wrappers that delegate to backend functions. 6 6 */ 7 7 8 - import { ipcMain, nativeTheme, dialog, BrowserWindow, app, screen, shell, webContents, net, Menu, clipboard } from 'electron'; 8 + import { ipcMain, nativeTheme, dialog, BrowserWindow, app, screen, webContents, net, Menu, clipboard } from 'electron'; 9 9 import fs from 'node:fs'; 10 10 import path from 'node:path'; 11 11 ··· 129 129 syncAll, 130 130 getSyncStatus, 131 131 } from './sync.js'; 132 - 133 - import { 134 - getBackupConfig, 135 - createBackup, 136 - listBackups, 137 - } from './backup.js'; 138 132 139 133 import { 140 134 detectModeFromUrl, ··· 1076 1070 entryId: 'main', 1077 1071 }; 1078 1072 DEBUG && console.log('[window-open] settings window: assigned trustedBuiltin tile-preload token'); 1073 + } 1074 + 1075 + // Special-case: peek://app/datastore/viewer.html uses api.datastore.* to 1076 + // display raw DB tables — not a registered v2 tile but needs tile-preload. 1077 + if (!tileWebPrefs && url === 'peek://app/datastore/viewer.html') { 1078 + const VIEWER_ID = 'datastore-viewer'; 1079 + const VIEWER_ENTRY = 'main'; 1080 + const viewerGrant = createTrustedBuiltinGrant(VIEWER_ID); 1081 + const viewerToken = generateToken(VIEWER_ID, VIEWER_ENTRY, viewerGrant); 1082 + tileWebPrefs = { 1083 + preload: getTilePreloadPath(), 1084 + additionalArguments: [ 1085 + `--tile-id=${VIEWER_ID}`, 1086 + `--tile-entry=${VIEWER_ENTRY}`, 1087 + `--tile-token=${viewerToken}`, 1088 + ], 1089 + tileId: VIEWER_ID, 1090 + entryId: VIEWER_ENTRY, 1091 + }; 1092 + DEBUG && console.log('[window-open] datastore-viewer window: assigned trustedBuiltin tile-preload token'); 1079 1093 } 1080 1094 1081 1095 // Canvas page host windows use tile-preload with a trustedBuiltin grant so ··· 2851 2865 * Register miscellaneous IPC handlers (shortcuts, pubsub, commands, etc.) 2852 2866 */ 2853 2867 export function registerMiscHandlers(onQuit: () => void): void { 2854 - // Get app-level preferences 2855 - ipcMain.handle('get-app-prefs', () => { 2856 - return getPrefs(); 2857 - }); 2858 - 2859 2868 // Check if current window is transient (opened when app wasn't focused) 2860 2869 // Used for IZUI policy: transient windows have different escape/mode behavior 2861 2870 ipcMain.handle('window-is-transient', (ev) => { ··· 3287 3296 }; 3288 3297 }); 3289 3298 3290 - // Open a path in the system file manager (Finder on macOS) 3291 - ipcMain.handle('shell-open-path', async (_ev, data) => { 3292 - try { 3293 - const pathToOpen = data.path || data; 3294 - // Ensure directory exists before opening 3295 - if (!fs.existsSync(pathToOpen)) { 3296 - fs.mkdirSync(pathToOpen, { recursive: true }); 3297 - } 3298 - await shell.openPath(pathToOpen); 3299 - return { success: true }; 3300 - } catch (error) { 3301 - const message = error instanceof Error ? error.message : String(error); 3302 - return { success: false, error: message }; 3303 - } 3304 - }); 3305 - 3306 - // Check if app is the default browser for http/https 3307 - ipcMain.handle('default-browser-status', async () => { 3308 - try { 3309 - const isDefaultHttp = app.isDefaultProtocolClient('http'); 3310 - const isDefaultHttps = app.isDefaultProtocolClient('https'); 3311 - return { isDefault: isDefaultHttp && isDefaultHttps }; 3312 - } catch (error) { 3313 - const message = error instanceof Error ? error.message : String(error); 3314 - return { isDefault: false, error: message }; 3315 - } 3316 - }); 3317 - 3318 - // Set app as the default browser for http/https 3319 - ipcMain.handle('set-default-browser', async () => { 3320 - try { 3321 - app.setAsDefaultProtocolClient('http'); 3322 - app.setAsDefaultProtocolClient('https'); 3323 - // Check if it actually worked 3324 - const isDefaultHttp = app.isDefaultProtocolClient('http'); 3325 - const isDefaultHttps = app.isDefaultProtocolClient('https'); 3326 - if (isDefaultHttp && isDefaultHttps) { 3327 - return { success: true }; 3328 - } else { 3329 - return { success: false, error: 'System did not accept the change. You may need to set the default browser in System Settings.' }; 3330 - } 3331 - } catch (error) { 3332 - const message = error instanceof Error ? error.message : String(error); 3333 - return { success: false, error: message }; 3334 - } 3335 - }); 3336 - 3337 3299 // Net fetch handler - proxies HTTP requests through main process to bypass CORS 3338 3300 // Used by extensions that need to fetch from external APIs (e.g., search suggestions) 3339 3301 ipcMain.handle('net-fetch', async (_ev, data: { url: string; options?: { method?: string; headers?: Record<string, string>; timeout?: number } }) => { ··· 3490 3452 try { 3491 3453 const status = getSyncStatus(); 3492 3454 return { success: true, data: status }; 3493 - } catch (error) { 3494 - const message = error instanceof Error ? error.message : String(error); 3495 - return { success: false, error: message }; 3496 - } 3497 - }); 3498 - } 3499 - 3500 - /** 3501 - * Register backup-related IPC handlers 3502 - */ 3503 - export function registerBackupHandlers(): void { 3504 - // Get backup configuration 3505 - ipcMain.handle('backup-get-config', async () => { 3506 - try { 3507 - const config = getBackupConfig(); 3508 - return { success: true, data: config }; 3509 - } catch (error) { 3510 - const message = error instanceof Error ? error.message : String(error); 3511 - return { success: false, error: message }; 3512 - } 3513 - }); 3514 - 3515 - // Create a backup manually 3516 - ipcMain.handle('backup-create', async () => { 3517 - try { 3518 - const result = await createBackup(); 3519 - return result; 3520 - } catch (error) { 3521 - const message = error instanceof Error ? error.message : String(error); 3522 - return { success: false, error: message }; 3523 - } 3524 - }); 3525 - 3526 - // List existing backups 3527 - ipcMain.handle('backup-list', async () => { 3528 - try { 3529 - const backups = listBackups(); 3530 - const config = getBackupConfig(); 3531 - return { 3532 - success: true, 3533 - data: { 3534 - backups, 3535 - backupDir: config.backupDir, 3536 - } 3537 - }; 3538 3455 } catch (error) { 3539 3456 const message = error instanceof Error ? error.message : String(error); 3540 3457 return { success: false, error: message }; ··· 3986 3903 registerExtensionHandlers(); 3987 3904 registerWindowHandlers(); 3988 3905 registerSyncHandlers(); 3989 - registerBackupHandlers(); 3990 3906 registerProfileHandlers(); 3991 3907 registerModesHandlers(); 3992 3908 registerWebExtensionHandlers();
+7 -7
tests/desktop/smoke.spec.ts
··· 4701 4701 4702 4702 test('backup-get-config returns config object', async () => { 4703 4703 const result = await bgWindow.evaluate(async () => { 4704 - return await (window as any).app.invoke('backup-get-config'); 4704 + return await (window as any).app.backup.getConfig(); 4705 4705 }); 4706 4706 4707 4707 expect(result.success).toBe(true); ··· 4714 4714 4715 4715 test('backup is disabled when backupDir is not configured', async () => { 4716 4716 const result = await bgWindow.evaluate(async () => { 4717 - return await (window as any).app.invoke('backup-get-config'); 4717 + return await (window as any).app.backup.getConfig(); 4718 4718 }); 4719 4719 4720 4720 expect(result.success).toBe(true); ··· 4725 4725 4726 4726 test('backup-create returns error when not configured', async () => { 4727 4727 const result = await bgWindow.evaluate(async () => { 4728 - return await (window as any).app.invoke('backup-create'); 4728 + return await (window as any).app.backup.create(); 4729 4729 }); 4730 4730 4731 4731 expect(result.success).toBe(false); ··· 4734 4734 4735 4735 test('backup-list returns empty when not configured', async () => { 4736 4736 const result = await bgWindow.evaluate(async () => { 4737 - return await (window as any).app.invoke('backup-list'); 4737 + return await (window as any).app.backup.list(); 4738 4738 }); 4739 4739 4740 4740 expect(result.success).toBe(true); ··· 4777 4777 4778 4778 // Verify config reflects the change 4779 4779 const configResult = await bgWindow.evaluate(async () => { 4780 - return await (window as any).app.invoke('backup-get-config'); 4780 + return await (window as any).app.backup.getConfig(); 4781 4781 }); 4782 4782 expect(configResult.success).toBe(true); 4783 4783 expect(configResult.data.backupDir).toBe(tempBackupDir); ··· 4785 4785 4786 4786 // Create a backup 4787 4787 const backupResult = await bgWindow.evaluate(async () => { 4788 - return await (window as any).app.invoke('backup-create'); 4788 + return await (window as any).app.backup.create(); 4789 4789 }); 4790 4790 expect(backupResult.success).toBe(true); 4791 4791 expect(backupResult.path).toBeTruthy(); ··· 4796 4796 4797 4797 // List backups - should have one 4798 4798 const listResult = await bgWindow.evaluate(async () => { 4799 - return await (window as any).app.invoke('backup-list'); 4799 + return await (window as any).app.backup.list(); 4800 4800 }); 4801 4801 expect(listResult.success).toBe(true); 4802 4802 expect(listResult.data.backups.length).toBe(1);