experiments in a post-browser web
10
fork

Configure Feed

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

feat(tile-launcher): relaunchTile(tileId) — close + revoke + re-read manifest + launch

+67 -1
+67 -1
backend/electron/tile-launcher.ts
··· 45 45 clearAllTokens, 46 46 } from './tile-tokens.js'; 47 47 import { scopes, publish, getSystemAddress, unsubscribeAllByPrefix } from './pubsub.js'; 48 - import { DEBUG } from './config.js'; 48 + import { DEBUG, getTilePreloadPath } from './config.js'; 49 49 import { loadSchemaDefaults } from './tile-settings-defaults.js'; 50 + import { getExtensionPath } from './protocol.js'; 50 51 51 52 // Short grace period given to tiles to run their `api.onShutdown()` callbacks 52 53 // before the BrowserWindow is forcibly closed. Kept small so app-quit and ··· 609 610 revokeTokensForTile(tileId, entryId); 610 611 611 612 DEBUG && console.log(`[tile-launcher] Unloaded tile: ${key}`); 613 + } 614 + 615 + /** 616 + * Relaunch a tile — re-read the manifest from disk, close the old window 617 + * (if any), revoke its tokens, then call `launchTile()` with the fresh manifest. 618 + * 619 + * This is the v2 replacement for `createExtensionWindow(extId)` used by 620 + * `reloadExtension()` and `loadDevExtension()` in main.ts. See Phase 2.5 #3b 621 + * in `docs/v1-removal-plan.md`. 622 + * 623 + * Edge cases: 624 + * - Tile not currently running (no window): just launches fresh. 625 + * - Window already destroyed: skips close, still revokes tokens and relaunches. 626 + * - Manifest no longer parseable: returns null (logs error). 627 + * - `getTilePreloadPath()` not configured: returns null (logs error). 628 + */ 629 + export async function relaunchTile(tileId: string): Promise<TileLaunchResult | null> { 630 + const tilePath = getExtensionPath(tileId); 631 + if (!tilePath) { 632 + console.error(`[tile-launcher] relaunchTile: no path registered for tile ${tileId}`); 633 + return null; 634 + } 635 + 636 + const tilePreloadPath = getTilePreloadPath(); 637 + if (!tilePreloadPath) { 638 + console.error(`[tile-launcher] relaunchTile: tile preload path not configured — call initialize() first`); 639 + return null; 640 + } 641 + 642 + // Re-read manifest from disk so any changes (e.g. during dev reload) are picked up. 643 + const manifestPath = path.join(tilePath, 'manifest.json'); 644 + const parsed = parseManifestFile(manifestPath); 645 + if (!parsed || parsed.version !== 'v2' || !parsed.v2) { 646 + console.error(`[tile-launcher] relaunchTile: cannot re-read v2 manifest for ${tileId} at ${manifestPath}`); 647 + return null; 648 + } 649 + const manifest = parsed.v2; 650 + 651 + // Determine which entry to (re)launch — use the first entry, matching the 652 + // pattern used in loadV2Tile / tile-compat. 653 + const entry = manifest.tiles[0]; 654 + if (!entry) { 655 + console.error(`[tile-launcher] relaunchTile: manifest for ${tileId} has no tile entries`); 656 + return null; 657 + } 658 + 659 + // Close the existing window if one is running. 660 + const existingWin = tileWindows.get(`${tileId}:${entry.id}`); 661 + if (existingWin && !existingWin.isDestroyed()) { 662 + // Use unloadTile for clean shutdown (shutdown signal + token revoke + unsubscribe). 663 + await unloadTile(tileId, entry.id); 664 + } else { 665 + // No live window — still revoke any stale tokens from a previous run. 666 + revokeTokensForTile(tileId, entry.id); 667 + loadedManifests.delete(tileId); 668 + } 669 + 670 + DEBUG && console.log(`[tile-launcher] Relaunching ${tileId}:${entry.id} from ${tilePath}`); 671 + 672 + return launchTile({ 673 + tilePath, 674 + manifest, 675 + preloadPath: tilePreloadPath, 676 + entryId: entry.id, 677 + }); 612 678 } 613 679 614 680 // ─── Test Hooks ──────────────────────────────────────────────────────