experiments in a post-browser web
10
fork

Configure Feed

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

fix(tile-ipc): delegate tile:window:open to real window-open handler

The tile:window:open handler was a stub that returned success without
actually opening a window. v2 tiles (editor, groups, tags, etc.) calling
api.window.open() silently failed.

Fix by exporting a reference to the window-open handler function from
ipc.ts (invokeWindowOpen) which tile-ipc.ts can call directly. Preserves
all window-open behavior: canvas rendering, mode inheritance, key-based
reuse, IZUI session registration, etc.

+36 -7
+13 -2
backend/electron/ipc.ts
··· 2217 2217 */ 2218 2218 const pendingWindowKeys = new Set<string>(); 2219 2219 2220 + // Exported reference to the window-open handler so other IPC surfaces (like v2 tile 2221 + // IPC) can delegate to it without duplicating ~1300 lines of window creation logic. 2222 + // Populated by registerWindowHandlers() at startup. 2223 + // Use `any` for parameters to match the original implicit-any ergonomics of the 2224 + // IPC handler body (options is heavily dynamic). 2225 + // eslint-disable-next-line @typescript-eslint/no-explicit-any 2226 + export let invokeWindowOpen: ((ev: any, msg: any) => Promise<unknown>) | null = null; 2227 + 2220 2228 export function registerWindowHandlers(): void { 2221 - ipcMain.handle('window-open', async (ev, msg) => { 2229 + // eslint-disable-next-line @typescript-eslint/no-explicit-any 2230 + const windowOpenHandler = async (ev: any, msg: any) => { 2222 2231 DEBUG && console.log('window-open', msg); 2223 2232 2224 2233 const { url, options } = msg; ··· 3505 3514 const message = error instanceof Error ? error.message : String(error); 3506 3515 return { success: false, error: message }; 3507 3516 } 3508 - }); 3517 + }; 3518 + ipcMain.handle('window-open', windowOpenHandler); 3519 + invokeWindowOpen = windowOpenHandler; 3509 3520 3510 3521 // Toggle click-through on transparent windows 3511 3522 ipcMain.handle('window-set-ignore-mouse-events', (ev, msg) => {
+23 -5
backend/electron/tile-ipc.ts
··· 29 29 import { installFromBundle } from './feature-installer.js'; 30 30 import { resolveCapabilities, validateTileManifest, detectManifestVersion } from './tile-manifest.js'; 31 31 import type { CapabilityGrant, TileCapabilities } from './tile-manifest.js'; 32 + import { invokeWindowOpen } from './ipc.js'; 32 33 33 34 // ─── Helpers ───────────────────────────────────────────────────────── 34 35 ··· 394 395 395 396 // ── Window Management ── 396 397 397 - ipcMain.handle('tile:window:open', async (_event, args: { 398 + ipcMain.handle('tile:window:open', async (event, args: { 398 399 token: string; 399 400 url: string; 400 401 options?: Record<string, unknown>; ··· 413 414 return { error: 'Only peek:// URLs can be opened' }; 414 415 } 415 416 416 - // Delegate to main process window creation 417 - // The actual implementation would call openWindow from main.ts 418 - // For now, return the intent for the main process to handle 419 - return { success: true, url: args.url }; 417 + // Delegate to the main window-open handler (registered by registerWindowHandlers() 418 + // in ipc.ts). This is the single source of truth for window creation — handles 419 + // canvas rendering, mode inheritance, deduping, session registration, etc. 420 + if (!invokeWindowOpen) { 421 + console.error('[tile:window:open] invokeWindowOpen not initialized — registerWindowHandlers() must be called before tile IPC is used'); 422 + return { error: 'Window handler not initialized' }; 423 + } 424 + 425 + const source = `peek://${grant.tileId}/background`; 426 + DEBUG && console.log(`[tile:window:open] ${grant.tileId} opening ${args.url}`); 427 + try { 428 + return await invokeWindowOpen(event, { 429 + source, 430 + url: args.url, 431 + options: args.options || {}, 432 + }); 433 + } catch (error) { 434 + const message = error instanceof Error ? error.message : String(error); 435 + console.error(`[tile:window:open] failed for ${grant.tileId}:`, message); 436 + return { success: false, error: message }; 437 + } 420 438 }); 421 439 422 440 ipcMain.on('tile:window:close', (_event, args: {