@dimina-kit/devtools 0.4.0-dev.20260824071518 → 0.4.0-dev.20260828161241

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/dist/main/api.d.ts +1 -1
  2. package/dist/main/app/app.js +59 -2
  3. package/dist/main/index.bundle.js +986 -245
  4. package/dist/main/ipc/index.d.ts +2 -0
  5. package/dist/main/ipc/index.js +2 -0
  6. package/dist/main/ipc/popover.js +1 -1
  7. package/dist/main/ipc/project-create.d.ts +15 -0
  8. package/dist/main/ipc/project-create.js +26 -0
  9. package/dist/main/ipc/projects.d.ts +1 -1
  10. package/dist/main/ipc/projects.js +36 -1
  11. package/dist/main/ipc/settings.js +2 -1
  12. package/dist/main/ipc/simulator-module.d.ts +4 -3
  13. package/dist/main/ipc/simulator-module.js +4 -5
  14. package/dist/main/ipc/tooltip.js +1 -1
  15. package/dist/main/ipc/views.d.ts +15 -1
  16. package/dist/main/ipc/views.js +61 -4
  17. package/dist/main/runtime/miniapp-runtime.d.ts +87 -19
  18. package/dist/main/services/notifications/renderer-notifier.d.ts +30 -1
  19. package/dist/main/services/notifications/renderer-notifier.js +23 -1
  20. package/dist/main/services/projects/create-project-service.js +9 -2
  21. package/dist/main/services/projects/local-provider.js +6 -0
  22. package/dist/main/services/projects/project-repository.d.ts +29 -1
  23. package/dist/main/services/projects/project-repository.js +151 -17
  24. package/dist/main/services/projects/types.d.ts +13 -2
  25. package/dist/main/services/update/update-manager.d.ts +17 -3
  26. package/dist/main/services/update/update-manager.js +25 -6
  27. package/dist/main/services/views/host-dialog-port-channel.d.ts +18 -0
  28. package/dist/main/services/views/host-dialog-port-channel.js +15 -0
  29. package/dist/main/services/views/host-dialog-session-runtime.d.ts +10 -0
  30. package/dist/main/services/views/host-dialog-session-runtime.js +17 -0
  31. package/dist/main/services/views/host-dialog-view.d.ts +95 -0
  32. package/dist/main/services/views/host-dialog-view.js +147 -0
  33. package/dist/main/services/views/host-sidebar-port-channel.d.ts +18 -0
  34. package/dist/main/services/views/host-sidebar-port-channel.js +15 -0
  35. package/dist/main/services/views/host-sidebar-session-runtime.d.ts +10 -0
  36. package/dist/main/services/views/host-sidebar-session-runtime.js +17 -0
  37. package/dist/main/services/views/host-sidebar-view.d.ts +59 -0
  38. package/dist/main/services/views/host-sidebar-view.js +44 -0
  39. package/dist/main/services/views/host-slot-port-channel.d.ts +107 -0
  40. package/dist/main/services/views/host-slot-port-channel.js +261 -0
  41. package/dist/main/services/views/host-slot-session-runtime.d.ts +40 -0
  42. package/dist/main/services/views/host-slot-session-runtime.js +50 -0
  43. package/dist/main/services/views/host-slot-view.d.ts +109 -0
  44. package/dist/main/services/views/host-slot-view.js +147 -0
  45. package/dist/main/services/views/host-toolbar-port-channel.d.ts +6 -91
  46. package/dist/main/services/views/host-toolbar-port-channel.js +10 -243
  47. package/dist/main/services/views/host-toolbar-session-runtime.d.ts +5 -30
  48. package/dist/main/services/views/host-toolbar-session-runtime.js +9 -47
  49. package/dist/main/services/views/host-toolbar-view.d.ts +34 -7
  50. package/dist/main/services/views/host-toolbar-view.js +30 -224
  51. package/dist/main/services/views/managed-web-contents-view.d.ts +48 -0
  52. package/dist/main/services/views/managed-web-contents-view.js +123 -0
  53. package/dist/main/services/views/overlay-panels-view.d.ts +23 -0
  54. package/dist/main/services/views/overlay-panels-view.js +93 -4
  55. package/dist/main/services/views/placement-reconciler.d.ts +14 -2
  56. package/dist/main/services/views/placement-reconciler.js +27 -0
  57. package/dist/main/services/views/placement-test-driver.d.ts +1 -0
  58. package/dist/main/services/views/placement-test-driver.js +3 -0
  59. package/dist/main/services/views/view-manager-devtools-host-test-fixtures.js +3 -1
  60. package/dist/main/services/views/view-manager.d.ts +10 -78
  61. package/dist/main/services/views/view-manager.js +34 -3
  62. package/dist/main/services/workbench-context.d.ts +18 -4
  63. package/dist/main/services/workbench-context.js +1 -0
  64. package/dist/main/services/workspace/workspace-service.d.ts +2 -0
  65. package/dist/main/services/workspace/workspace-service.js +14 -0
  66. package/dist/main/utils/paths.d.ts +4 -0
  67. package/dist/main/utils/paths.js +4 -0
  68. package/dist/main/utils/sender-policy.js +10 -0
  69. package/dist/native-host/common/common.js +65 -62
  70. package/dist/native-host/render/render.js +2230 -2052
  71. package/dist/native-host/service/service.js +2 -2
  72. package/dist/preload/runtime/host-dialog-advertiser.d.ts +22 -0
  73. package/dist/preload/runtime/host-dialog-advertiser.js +37 -0
  74. package/dist/preload/runtime/host-dialog-port.d.ts +44 -0
  75. package/dist/preload/runtime/host-dialog-port.js +53 -0
  76. package/dist/preload/runtime/host-dialog-runtime.d.ts +28 -0
  77. package/dist/preload/runtime/host-dialog-runtime.js +36 -0
  78. package/dist/preload/runtime/host-sidebar-advertiser.d.ts +19 -0
  79. package/dist/preload/runtime/host-sidebar-advertiser.js +35 -0
  80. package/dist/preload/runtime/host-sidebar-port.d.ts +44 -0
  81. package/dist/preload/runtime/host-sidebar-port.js +53 -0
  82. package/dist/preload/runtime/host-sidebar-runtime.d.ts +28 -0
  83. package/dist/preload/runtime/host-sidebar-runtime.js +36 -0
  84. package/dist/preload/runtime/host-slot-port-bridge.d.ts +18 -0
  85. package/dist/preload/runtime/host-slot-port-bridge.js +112 -0
  86. package/dist/preload/runtime/host-toolbar-advertiser.d.ts +5 -13
  87. package/dist/preload/runtime/host-toolbar-advertiser.js +18 -38
  88. package/dist/preload/runtime/host-toolbar-port.d.ts +9 -0
  89. package/dist/preload/runtime/host-toolbar-port.js +11 -95
  90. package/dist/preload/runtime/wait-for-slot-root.d.ts +20 -0
  91. package/dist/preload/runtime/wait-for-slot-root.js +52 -0
  92. package/dist/preload/windows/host-dialog-runtime.cjs +353 -0
  93. package/dist/preload/windows/host-dialog-runtime.cjs.map +7 -0
  94. package/dist/preload/windows/host-dialog-runtime.d.ts +2 -0
  95. package/dist/preload/windows/host-dialog-runtime.js +13 -0
  96. package/dist/preload/windows/host-sidebar-runtime.cjs +354 -0
  97. package/dist/preload/windows/host-sidebar-runtime.cjs.map +7 -0
  98. package/dist/preload/windows/host-sidebar-runtime.d.ts +2 -0
  99. package/dist/preload/windows/host-sidebar-runtime.js +13 -0
  100. package/dist/preload/windows/host-toolbar-runtime.cjs +134 -51
  101. package/dist/preload/windows/host-toolbar-runtime.cjs.map +3 -3
  102. package/dist/preload/windows/simulator.cjs.map +1 -1
  103. package/dist/renderer/assets/button-D5Q2wkXq.js +2 -0
  104. package/dist/renderer/assets/constants-D7DfVqMp.js +2 -0
  105. package/dist/renderer/assets/constants-D8zsejFq.js +2 -0
  106. package/dist/renderer/assets/createLucideIcon-Bqi8hpdi.js +2 -0
  107. package/dist/renderer/assets/dialog-e1TecTOY.js +46 -0
  108. package/dist/renderer/assets/dist-DKWdE1TK.js +2 -0
  109. package/dist/renderer/assets/hostSidebarDefault-B3yLfy8j.js +2 -0
  110. package/dist/renderer/assets/index-CsPD68N_.js +5 -0
  111. package/dist/renderer/assets/input-Ct3alvkq.js +2 -0
  112. package/dist/renderer/assets/ipc-channels-overlays-LsDzGAtV.js +2 -0
  113. package/dist/renderer/assets/jsx-runtime-2vXHouwr.css +1 -0
  114. package/dist/renderer/assets/jsx-runtime-DGLHmmOq.js +9 -0
  115. package/dist/renderer/assets/popover-Dix5cm_b.js +2 -0
  116. package/dist/renderer/assets/project-api-k7Oq9iaq.js +2 -0
  117. package/dist/renderer/assets/projectCreateDialog-Bbjz75bP.js +2 -0
  118. package/dist/renderer/assets/select-acGb0AmJ.js +2 -0
  119. package/dist/renderer/assets/settings-CQrTMr43.js +2 -0
  120. package/dist/renderer/assets/settings-api-CrUQ9rYV.js +2 -0
  121. package/dist/renderer/assets/settings-tab-bar-Cw1kVIf2.js +2 -0
  122. package/dist/renderer/assets/tooltip-B_-_YVbw.js +2 -0
  123. package/dist/renderer/assets/types-CsEKtFyr.js +2 -0
  124. package/dist/renderer/assets/updateDialog-NsF8223A.js +2 -0
  125. package/dist/renderer/assets/utils-kfQov6Pa.js +2 -0
  126. package/dist/renderer/assets/view-api-CLn3rcQE.js +2 -0
  127. package/dist/renderer/assets/{workbenchSettings-oq_EyfKf.js → workbenchSettings-CV4LVA9b.js} +3 -3
  128. package/dist/renderer/entries/host-sidebar-default/index.html +21 -0
  129. package/dist/renderer/entries/main/index.html +17 -8
  130. package/dist/renderer/entries/popover/index.html +10 -7
  131. package/dist/renderer/entries/project-create-dialog/index.html +27 -0
  132. package/dist/renderer/entries/settings/index.html +10 -7
  133. package/dist/renderer/entries/tooltip/index.html +5 -4
  134. package/dist/renderer/entries/update-dialog/index.html +25 -0
  135. package/dist/renderer/entries/workbench-settings/index.html +11 -7
  136. package/dist/service-host/preload.cjs +10 -0
  137. package/dist/shared/constants.d.ts +22 -0
  138. package/dist/shared/constants.js +22 -0
  139. package/dist/shared/ipc-channels-overlays.d.ts +156 -0
  140. package/dist/shared/ipc-channels-overlays.js +186 -0
  141. package/dist/shared/ipc-channels.d.ts +4 -77
  142. package/dist/shared/ipc-channels.js +4 -98
  143. package/dist/shared/ipc-schemas.d.ts +44 -0
  144. package/dist/shared/ipc-schemas.js +55 -0
  145. package/dist/shared/types.d.ts +71 -0
  146. package/dist/shared/view-ids.d.ts +7 -0
  147. package/dist/shared/view-ids.js +10 -0
  148. package/package.json +8 -8
  149. package/dist/renderer/assets/constants-Bdz0LHdy.js +0 -2
  150. package/dist/renderer/assets/index-CtznrmHR.js +0 -49
  151. package/dist/renderer/assets/input-Dmm6nob5.js +0 -2
  152. package/dist/renderer/assets/ipc-transport-BOg0gR9W.js +0 -9
  153. package/dist/renderer/assets/ipc-transport-DgQhZaE9.css +0 -1
  154. package/dist/renderer/assets/popover-Cd1FEGOX.js +0 -2
  155. package/dist/renderer/assets/select-BaYox7If.js +0 -2
  156. package/dist/renderer/assets/settings-BXvwuFaz.js +0 -2
  157. package/dist/renderer/assets/settings-api-Bo9GbYqs.js +0 -2
  158. package/dist/renderer/assets/settings-tab-bar-Beia6lMr.js +0 -2
  159. package/dist/renderer/assets/tooltip-DfQqK3Sk.js +0 -2
  160. package/dist/renderer/assets/view-api-nn69je7A.js +0 -2
@@ -31,6 +31,9 @@ var DEFAULT_CDP_PORT = 9222;
31
31
  var DEFAULT_SCENE = 1001;
32
32
  var HEADER_H = 40;
33
33
  var HOST_TOOLBAR_RUNTIME_MARKER = "--dimina-host-toolbar";
34
+ var HOST_SIDEBAR_RUNTIME_MARKER = "--dimina-host-sidebar";
35
+ var HOST_DIALOG_RUNTIME_MARKER = "--dimina-host-dialog";
36
+ var HOST_SIDEBAR_DEFAULT_WIDTH = 56;
34
37
 
35
38
  // src/main/services/settings/index.ts
36
39
  import { app, nativeTheme } from "electron";
@@ -482,10 +485,14 @@ var ProjectsChannel = {
482
485
  List: "projects:list",
483
486
  Add: "projects:add",
484
487
  Remove: "projects:remove",
488
+ /** Edit an existing record's name / icon; its path stays the identity. */
489
+ Update: "projects:update",
485
490
  /** Merged + sanitized template catalog for the create-project dialog. */
486
491
  ListTemplates: "projects:listTemplates",
487
492
  /** Host-supplied create-project dialog hook (returns input or null). */
488
493
  OpenCreateDialog: "projects:openCreateDialog",
494
+ /** Host-supplied edit-project dialog hook; `null` means no hook is configured. */
495
+ OpenEditDialog: "projects:openEditDialog",
489
496
  /** Server-side scaffold + register (delegates to create-project-service). */
490
497
  Create: "projects:create",
491
498
  /** Default values used to pre-fill the create-project dialog (baseDir). */
@@ -494,64 +501,6 @@ var ProjectsChannel = {
494
501
  var DialogChannel = {
495
502
  OpenDirectory: "dialog:openDirectory"
496
503
  };
497
- var ViewChannel = {
498
- /**
499
- * Reverse size-advertiser: the host-toolbar WCV's OWN renderer advertises its
500
- * intrinsic content height so main reserves exactly that much. Payload
501
- * `{ axis: 'block', extent }`. fire-and-forget (send), NOT invoke.
502
- */
503
- HostToolbarAdvertiseHeight: "view:host-toolbar:advertise-height",
504
- /**
505
- * main → host-toolbar WCV renderer: per-load MessagePort handshake for the
506
- * gated narrow channel. On every toolbar `did-finish-load` main creates a
507
- * `MessageChannelMain` and transfers port2 here
508
- * (`wc.postMessage(HostToolbarPort, null, [port2])`); the session-resident
509
- * toolbar runtime preload receives it via `event.ports[0]` and bridges it to
510
- * the page as `window.diminaHostToolbar`. Envelope both directions:
511
- * `{ channel: string, payload: unknown }`.
512
- */
513
- HostToolbarPort: "view:host-toolbar:port",
514
- /**
515
- * main → main-window renderer: push the reserved host-toolbar height so the
516
- * renderer placeholder div resizes (closing the dynamic-height loop).
517
- */
518
- HostToolbarHeightChanged: "view:host-toolbar:height-changed",
519
- /**
520
- * main ← main-window renderer (invoke): pull the last NOTIFIED toolbar
521
- * height retained in main. Mount-time replay companion to
522
- * `HostToolbarHeightChanged`: the push listener mounts with the project
523
- * view and the toolbar's size-advertiser deduplicates (never re-reports),
524
- * so a height pushed while no project view was mounted would otherwise be
525
- * lost forever (cold start on the project list races it; close-project →
526
- * reopen hits it deterministically). No payload; resolves a number.
527
- */
528
- HostToolbarGetHeight: "view:host-toolbar:get-height",
529
- /**
530
- * Renderer → main: the window-level placement snapshot (one monotonic epoch
531
- * per commit tick, one generation per renderer lifetime) that drives the view
532
- * reconciler. The single source of truth for every managed native view's
533
- * bounds/visibility/z-order — supersedes the per-view bounds channels above.
534
- * invoke.
535
- */
536
- PlacementSnapshot: "view:placement-snapshot"
537
- };
538
- var PopoverChannel = {
539
- Show: "popover:show",
540
- Hide: "popover:hide",
541
- Relaunch: "popover:relaunch",
542
- Closed: "popover:closed",
543
- Init: "popover:init"
544
- };
545
- var OverlayChannel = {
546
- Ready: "overlay:ready"
547
- };
548
- var TooltipChannel = {
549
- Prepare: "tooltip:prepare",
550
- Show: "tooltip:show",
551
- Hide: "tooltip:hide",
552
- Init: "tooltip:init",
553
- Measured: "tooltip:measured"
554
- };
555
504
  var WindowChannel = {
556
505
  NavigateBack: "window:navigateBack",
557
506
  OpenProject: "window:openProject",
@@ -574,19 +523,6 @@ var InternalDevtoolsChannel = {
574
523
  // its own dedicated window (see internal-devtools-window/index.ts).
575
524
  Open: "internal-devtools:open"
576
525
  };
577
- var SettingsChannel = {
578
- SetVisible: "settings:setVisible",
579
- ConfigChanged: "settings:configChanged",
580
- ProjectSettingsChanged: "settings:projectSettingsChanged",
581
- Init: "settings:init"
582
- };
583
- var UpdateChannel = {
584
- Check: "updates:check",
585
- Download: "updates:download",
586
- Install: "updates:install",
587
- DownloadProgress: "updates:downloadProgress",
588
- Available: "updates:available"
589
- };
590
526
 
591
527
  // src/main/ipc/project-fs.ts
592
528
  import { WATCH_IGNORE_DIRS } from "@dimina-kit/devkit/watch-ignore";
@@ -921,7 +857,7 @@ function registerProjectFsIpc(ctx) {
921
857
  }
922
858
 
923
859
  // src/main/app/app.ts
924
- import { app as app13, BrowserWindow as BrowserWindow6, nativeImage, session as session2 } from "electron";
860
+ import { app as app13, BrowserWindow as BrowserWindow5, nativeImage, session as session2 } from "electron";
925
861
  import fs10 from "fs";
926
862
  import path19 from "path";
927
863
 
@@ -954,6 +890,14 @@ var hostToolbarRuntimePreloadPath = path3.join(
954
890
  devtoolsPackageRoot,
955
891
  "dist/preload/windows/host-toolbar-runtime.cjs"
956
892
  );
893
+ var hostSidebarRuntimePreloadPath = path3.join(
894
+ devtoolsPackageRoot,
895
+ "dist/preload/windows/host-sidebar-runtime.cjs"
896
+ );
897
+ var hostDialogRuntimePreloadPath = path3.join(
898
+ devtoolsPackageRoot,
899
+ "dist/preload/windows/host-dialog-runtime.cjs"
900
+ );
957
901
  var simulatorDir = path3.join(devtoolsPackageRoot, "dist/simulator");
958
902
  var runtimeAssetPaths = {
959
903
  root: path3.join(devtoolsPackageRoot, "dist"),
@@ -1595,6 +1539,10 @@ function createWorkbenchSenderPolicy(ctx) {
1595
1539
  if (popoverViewId != null && sender.id === popoverViewId) return true;
1596
1540
  const tooltipViewId = ctx.views.getTooltipWebContentsId();
1597
1541
  if (tooltipViewId != null && sender.id === tooltipViewId) return true;
1542
+ const projectCreateDialogViewId = ctx.views.getProjectCreateDialogWebContentsId();
1543
+ if (projectCreateDialogViewId != null && sender.id === projectCreateDialogViewId) return true;
1544
+ const updateDialogViewId = ctx.views.getUpdateDialogWebContentsId();
1545
+ if (updateDialogViewId != null && sender.id === updateDialogViewId) return true;
1598
1546
  return false;
1599
1547
  };
1600
1548
  }
@@ -1614,6 +1562,148 @@ var defaultAdapter = {
1614
1562
  }
1615
1563
  };
1616
1564
 
1565
+ // src/shared/ipc-channels-overlays.ts
1566
+ var ViewChannel = {
1567
+ /**
1568
+ * Reverse size-advertiser: the host-toolbar WCV's OWN renderer advertises its
1569
+ * intrinsic content height so main reserves exactly that much. Payload
1570
+ * `{ axis: 'block', extent }`. fire-and-forget (send), NOT invoke.
1571
+ */
1572
+ HostToolbarAdvertiseHeight: "view:host-toolbar:advertise-height",
1573
+ /**
1574
+ * main → host-toolbar WCV renderer: per-load MessagePort handshake for the
1575
+ * gated narrow channel. On every toolbar `did-finish-load` main creates a
1576
+ * `MessageChannelMain` and transfers port2 here
1577
+ * (`wc.postMessage(HostToolbarPort, null, [port2])`); the session-resident
1578
+ * toolbar runtime preload receives it via `event.ports[0]` and bridges it to
1579
+ * the page as `window.diminaHostToolbar`. Envelope both directions:
1580
+ * `{ channel: string, payload: unknown }`.
1581
+ */
1582
+ HostToolbarPort: "view:host-toolbar:port",
1583
+ /**
1584
+ * main → main-window renderer: push the reserved host-toolbar height so the
1585
+ * renderer placeholder div resizes (closing the dynamic-height loop).
1586
+ */
1587
+ HostToolbarHeightChanged: "view:host-toolbar:height-changed",
1588
+ /**
1589
+ * main ← main-window renderer (invoke): pull the last NOTIFIED toolbar
1590
+ * height retained in main. Mount-time replay companion to
1591
+ * `HostToolbarHeightChanged`: the push listener mounts with the project
1592
+ * view and the toolbar's size-advertiser deduplicates (never re-reports),
1593
+ * so a height pushed while no project view was mounted would otherwise be
1594
+ * lost forever (cold start on the project list races it; close-project →
1595
+ * reopen hits it deterministically). No payload; resolves a number.
1596
+ */
1597
+ HostToolbarGetHeight: "view:host-toolbar:get-height",
1598
+ /**
1599
+ * Reverse size-advertiser for the host-sidebar WCV, mirroring
1600
+ * `HostToolbarAdvertiseHeight` on the inline (width) axis instead of block.
1601
+ * Payload `{ axis: 'inline', extent }`. fire-and-forget (send), NOT invoke.
1602
+ */
1603
+ HostSidebarAdvertiseWidth: "view:host-sidebar:advertise-width",
1604
+ /**
1605
+ * main → host-sidebar WCV renderer: per-load MessagePort handshake, same
1606
+ * contract as `HostToolbarPort` (see that entry).
1607
+ */
1608
+ HostSidebarPort: "view:host-sidebar:port",
1609
+ /**
1610
+ * main → main-window renderer: push the reserved host-sidebar width so the
1611
+ * renderer placeholder div resizes, mirroring `HostToolbarHeightChanged`.
1612
+ */
1613
+ HostSidebarWidthChanged: "view:host-sidebar:width-changed",
1614
+ /**
1615
+ * main ← main-window renderer (invoke): pull the last NOTIFIED sidebar
1616
+ * width, mirroring `HostToolbarGetHeight`'s mount-time replay role.
1617
+ */
1618
+ HostSidebarGetWidth: "view:host-sidebar:get-width",
1619
+ /**
1620
+ * main → main-window renderer: push the project category (`Project.type`)
1621
+ * selected in the host-sidebar's content — devtools' own default icon rail,
1622
+ * or any downstream replacement that sends on the same channel. No
1623
+ * pull/replay companion like `HostSidebarGetWidth`: the default category is
1624
+ * a stable initial value regardless of load-order, and nothing is ever sent
1625
+ * before the main-window renderer (and thus `ProjectListScreen`) is already
1626
+ * mounted.
1627
+ */
1628
+ HostSidebarCategorySelected: "view:host-sidebar:category-selected",
1629
+ /**
1630
+ * Reverse size-advertiser for the host-dialog WCV. Unlike the toolbar/sidebar
1631
+ * (single-axis, `setBaseDesired`-placed strips), the dialog is a BOTH-AXES
1632
+ * overlay positioned by `setOverlayDesired` — main centers it in the main
1633
+ * window once it knows both dimensions. One channel carries either axis'
1634
+ * report (`{ axis: 'block' | 'inline', extent }`); the dialog's own content
1635
+ * advertises both from the same root (see `host-dialog-advertiser.ts`).
1636
+ * fire-and-forget (send), NOT invoke.
1637
+ *
1638
+ * No `HostDialogSizeChanged` / `HostDialogGetSize` counterparts: those exist
1639
+ * for toolbar/sidebar so a renderer-owned PLACEHOLDER can replay a size it
1640
+ * missed. The dialog has no such placeholder — it is a main-driven overlay
1641
+ * shown/hidden on demand (`hostDialog.show()`/`hide()`), so there is nothing
1642
+ * in the renderer to replay a size into.
1643
+ */
1644
+ HostDialogAdvertiseSize: "view:host-dialog:advertise-size",
1645
+ /**
1646
+ * main → host-dialog WCV renderer: per-load MessagePort handshake, same
1647
+ * contract as `HostToolbarPort` (see that entry).
1648
+ */
1649
+ HostDialogPort: "view:host-dialog:port",
1650
+ /**
1651
+ * Renderer → main: the window-level placement snapshot (one monotonic epoch
1652
+ * per commit tick, one generation per renderer lifetime) that drives the view
1653
+ * reconciler. The single source of truth for every managed native view's
1654
+ * bounds/visibility/z-order — supersedes the per-view bounds channels above.
1655
+ * invoke.
1656
+ */
1657
+ PlacementSnapshot: "view:placement-snapshot",
1658
+ /**
1659
+ * main ← main-window renderer (invoke): allocate a fresh placement
1660
+ * generation seed for this renderer bootstrap. See
1661
+ * renderer-placement-generation.ts for why the seed comes from main
1662
+ * (a wall-clock `Date.now()` seed is not guaranteed to exceed main's
1663
+ * still-standing high-water mark across two reloads that happen faster
1664
+ * than the clock's resolution). No payload; resolves a number.
1665
+ */
1666
+ AllocatePlacementGeneration: "view:allocate-placement-generation"
1667
+ };
1668
+ var PopoverChannel = {
1669
+ Show: "popover:show",
1670
+ Hide: "popover:hide",
1671
+ Relaunch: "popover:relaunch",
1672
+ Closed: "popover:closed",
1673
+ Init: "popover:init"
1674
+ };
1675
+ var OverlayChannel = {
1676
+ Ready: "overlay:ready"
1677
+ };
1678
+ var TooltipChannel = {
1679
+ Prepare: "tooltip:prepare",
1680
+ Show: "tooltip:show",
1681
+ Hide: "tooltip:hide",
1682
+ Init: "tooltip:init",
1683
+ Measured: "tooltip:measured"
1684
+ };
1685
+ var ProjectCreateChannel = {
1686
+ Show: "projectCreate:show",
1687
+ Init: "projectCreate:init",
1688
+ Submit: "projectCreate:submit",
1689
+ Cancel: "projectCreate:cancel",
1690
+ Submitted: "projectCreate:submitted"
1691
+ };
1692
+ var SettingsChannel = {
1693
+ SetVisible: "settings:setVisible",
1694
+ ConfigChanged: "settings:configChanged",
1695
+ ProjectSettingsChanged: "settings:projectSettingsChanged",
1696
+ Init: "settings:init"
1697
+ };
1698
+ var UpdateChannel = {
1699
+ Check: "updates:check",
1700
+ Download: "updates:download",
1701
+ Install: "updates:install",
1702
+ DownloadProgress: "updates:downloadProgress",
1703
+ Available: "updates:available",
1704
+ Close: "updates:close"
1705
+ };
1706
+
1617
1707
  // src/main/services/notifications/renderer-notifier.ts
1618
1708
  function liveWebContents(wc) {
1619
1709
  if (!wc) return null;
@@ -1652,9 +1742,18 @@ function createRendererNotifier(ctx) {
1652
1742
  hostToolbarHeightChanged(height) {
1653
1743
  sendToMain(ViewChannel.HostToolbarHeightChanged, height);
1654
1744
  },
1745
+ hostSidebarWidthChanged(width) {
1746
+ sendToMain(ViewChannel.HostSidebarWidthChanged, width);
1747
+ },
1748
+ hostSidebarCategorySelected(category) {
1749
+ sendToMain(ViewChannel.HostSidebarCategorySelected, category);
1750
+ },
1655
1751
  editorOpenFile(payload) {
1656
1752
  sendToMain(EditorChannel.OpenFile, payload);
1657
1753
  },
1754
+ projectCreateSubmitted(payload) {
1755
+ sendToMain(ProjectCreateChannel.Submitted, payload);
1756
+ },
1658
1757
  popoverInit(popoverView, payload) {
1659
1758
  const wc = liveWebContents(popoverView.webContents);
1660
1759
  if (!wc) return;
@@ -1665,6 +1764,16 @@ function createRendererNotifier(ctx) {
1665
1764
  if (!wc) return;
1666
1765
  wc.send(TooltipChannel.Init, payload);
1667
1766
  },
1767
+ projectCreateInit(dialogView, payload) {
1768
+ const wc = liveWebContents(dialogView.webContents);
1769
+ if (!wc) return;
1770
+ wc.send(ProjectCreateChannel.Init, payload);
1771
+ },
1772
+ updateAvailable(dialogView, payload) {
1773
+ const wc = liveWebContents(dialogView.webContents);
1774
+ if (!wc) return;
1775
+ wc.send(UpdateChannel.Available, payload);
1776
+ },
1668
1777
  settingsInit(payload) {
1669
1778
  const wc = liveWebContents(ctx.views.getSettingsWebContents());
1670
1779
  if (!wc) return;
@@ -1933,6 +2042,7 @@ function createPlacementReconciler(ctx) {
1933
2042
  let placementState = createInitialState();
1934
2043
  let epochCounter = 0;
1935
2044
  let rendererGeneration = 0;
2045
+ let allocatedGeneration = 0;
1936
2046
  const appliedActual = /* @__PURE__ */ new Map();
1937
2047
  const baseDesired = /* @__PURE__ */ new Map();
1938
2048
  const overlayDesired = /* @__PURE__ */ new Map();
@@ -2022,6 +2132,12 @@ function createPlacementReconciler(ctx) {
2022
2132
  placementState = { ...placementState, actual: cloneAppliedActual() };
2023
2133
  }
2024
2134
  function setPlacementSnapshot(snapshot) {
2135
+ if (snapshot.generation < rendererGeneration) {
2136
+ console.warn(
2137
+ `[placement-reconciler] snapshot generation ${snapshot.generation} is behind the current ${rendererGeneration}; dropping without applying its content`
2138
+ );
2139
+ return;
2140
+ }
2025
2141
  rendererGeneration = snapshot.generation;
2026
2142
  baseDesired.clear();
2027
2143
  for (const v of snapshot.views) baseDesired.set(v.viewId, v);
@@ -2059,7 +2175,11 @@ function createPlacementReconciler(ctx) {
2059
2175
  deleteOverlayDesired: (viewId) => {
2060
2176
  overlayDesired.delete(viewId);
2061
2177
  },
2062
- hasOverlayDesired: (viewId) => overlayDesired.has(viewId)
2178
+ hasOverlayDesired: (viewId) => overlayDesired.has(viewId),
2179
+ allocateGeneration: () => {
2180
+ allocatedGeneration = Math.max(allocatedGeneration, rendererGeneration) + 1;
2181
+ return allocatedGeneration;
2182
+ }
2063
2183
  };
2064
2184
  }
2065
2185
 
@@ -2072,16 +2192,26 @@ var VIEW_ID = {
2072
2192
  simulatorDevtools: "simulator-devtools",
2073
2193
  workbench: "workbench",
2074
2194
  hostToolbar: "host-toolbar",
2195
+ hostSidebar: "host-sidebar",
2196
+ hostDialog: "host-dialog",
2075
2197
  settings: "settings",
2076
2198
  popover: "popover",
2077
- tooltip: "tooltip"
2199
+ tooltip: "tooltip",
2200
+ projectCreateDialog: "project-create-dialog",
2201
+ updateDialog: "update-dialog"
2078
2202
  };
2079
2203
  var VIEW_LAYER = {
2080
2204
  base: 0,
2081
2205
  hostToolbar: 5,
2206
+ hostSidebar: 5,
2082
2207
  settings: 10,
2083
2208
  popover: 20,
2084
- tooltip: 30
2209
+ tooltip: 30,
2210
+ // devtools' own ProjectCreateDialog/UpdateDialog panels (createOverlayPanel).
2211
+ dialog: 40,
2212
+ // Host-controlled fully-custom dialog (loadURL-level takeover); sits above
2213
+ // devtools' own dialog layer so host content is never occluded by it.
2214
+ hostDialog: 45
2085
2215
  };
2086
2216
 
2087
2217
  // src/main/services/views/workbench-view.ts
@@ -4855,34 +4985,44 @@ function createDevtoolsHost(ctx, reconciler, deps) {
4855
4985
  };
4856
4986
  }
4857
4987
 
4858
- // src/main/services/views/host-toolbar-view.ts
4859
- import { WebContentsView as WebContentsView5 } from "electron";
4988
+ // src/main/services/views/host-slot-session-runtime.ts
4989
+ import { session } from "electron";
4990
+ function createHostSlotSessionRuntime(preloadPath) {
4991
+ let refCount = 0;
4992
+ let registrationId = null;
4993
+ return {
4994
+ acquire() {
4995
+ if (refCount === 0) {
4996
+ registrationId = session.defaultSession.registerPreloadScript({
4997
+ type: "frame",
4998
+ filePath: preloadPath
4999
+ });
5000
+ }
5001
+ refCount++;
5002
+ },
5003
+ release() {
5004
+ if (refCount === 0) return;
5005
+ refCount--;
5006
+ if (refCount === 0 && registrationId !== null) {
5007
+ session.defaultSession.unregisterPreloadScript(registrationId);
5008
+ registrationId = null;
5009
+ }
5010
+ }
5011
+ };
5012
+ }
4860
5013
 
4861
5014
  // src/main/services/views/host-toolbar-session-runtime.ts
4862
- import { session } from "electron";
4863
- var refCount = 0;
4864
- var registrationId = null;
5015
+ var runtime = createHostSlotSessionRuntime(hostToolbarRuntimePreloadPath);
4865
5016
  function acquireHostToolbarSessionRuntime() {
4866
- if (refCount === 0) {
4867
- registrationId = session.defaultSession.registerPreloadScript({
4868
- type: "frame",
4869
- filePath: hostToolbarRuntimePreloadPath
4870
- });
4871
- }
4872
- refCount++;
5017
+ runtime.acquire();
4873
5018
  }
4874
5019
  function releaseHostToolbarSessionRuntime() {
4875
- if (refCount === 0) return;
4876
- refCount--;
4877
- if (refCount === 0 && registrationId !== null) {
4878
- session.defaultSession.unregisterPreloadScript(registrationId);
4879
- registrationId = null;
4880
- }
5020
+ runtime.release();
4881
5021
  }
4882
5022
 
4883
- // src/main/services/views/host-toolbar-port-channel.ts
5023
+ // src/main/services/views/host-slot-port-channel.ts
4884
5024
  import { MessageChannelMain } from "electron";
4885
- function createHostToolbarPortChannel(opts) {
5025
+ function createHostSlotPortChannel(opts) {
4886
5026
  let activePort = null;
4887
5027
  let activeWc = null;
4888
5028
  let state = "absent";
@@ -4894,7 +5034,14 @@ function createHostToolbarPortChannel(opts) {
4894
5034
  const { channel, payload } = data;
4895
5035
  if (typeof channel !== "string") return;
4896
5036
  for (const entry of [...handlers2]) {
4897
- if (entry.channel === channel) entry.handler(payload);
5037
+ if (entry.channel === channel) invokeMessageHandler(entry.handler, payload);
5038
+ }
5039
+ }
5040
+ function invokeMessageHandler(handler, payload) {
5041
+ try {
5042
+ handler(payload);
5043
+ } catch (err2) {
5044
+ console.error(`${opts.logPrefix} onMessage handler threw:`, err2);
4898
5045
  }
4899
5046
  }
4900
5047
  function dropActivePort(close, next) {
@@ -4913,7 +5060,7 @@ function createHostToolbarPortChannel(opts) {
4913
5060
  try {
4914
5061
  handler();
4915
5062
  } catch (err2) {
4916
- console.error("[host-toolbar] onReady handler threw:", err2);
5063
+ console.error(`${opts.logPrefix} onReady handler threw:`, err2);
4917
5064
  }
4918
5065
  }
4919
5066
  function fireReadyHandlers() {
@@ -4932,7 +5079,7 @@ function createHostToolbarPortChannel(opts) {
4932
5079
  port1.on("close", () => {
4933
5080
  if (activePort === port1) dropActivePort(false, "absent");
4934
5081
  });
4935
- wc.postMessage(ViewChannel.HostToolbarPort, null, [port2]);
5082
+ wc.postMessage(opts.channel, null, [port2]);
4936
5083
  port1.start();
4937
5084
  activePort = port1;
4938
5085
  activeWc = wc;
@@ -4963,7 +5110,7 @@ function createHostToolbarPortChannel(opts) {
4963
5110
  onMessage(channel, handler) {
4964
5111
  if (typeof channel !== "string" || channel === "") {
4965
5112
  throw new TypeError(
4966
- "hostToolbar.onMessage: channel must be a non-empty string"
5113
+ `${opts.logPrefix} onMessage: channel must be a non-empty string`
4967
5114
  );
4968
5115
  }
4969
5116
  const entry = { channel, handler };
@@ -5011,135 +5158,401 @@ function createHostToolbarPortChannel(opts) {
5011
5158
  };
5012
5159
  }
5013
5160
 
5014
- // src/main/services/views/host-toolbar-view.ts
5015
- function createHostToolbarView(ctx, reconciler, deps) {
5016
- let hostToolbarView = null;
5017
- let hostToolbarPreloadOverride = null;
5018
- let hostToolbarRuntimeAcquired = false;
5019
- let hostToolbarHeightMode = "auto";
5020
- let hostToolbarLastHeight = 0;
5021
- const hostToolbarPort = createHostToolbarPortChannel({
5022
- isCurrent: (wc) => liveHostToolbarWebContents() === wc
5161
+ // src/main/services/views/host-toolbar-port-channel.ts
5162
+ function createHostToolbarPortChannel(opts) {
5163
+ return createHostSlotPortChannel({
5164
+ isCurrent: opts.isCurrent,
5165
+ channel: ViewChannel.HostToolbarPort,
5166
+ logPrefix: "[host-toolbar]"
5023
5167
  });
5024
- function liveHostToolbarWebContents() {
5025
- const wc = hostToolbarView?.webContents;
5168
+ }
5169
+
5170
+ // src/main/services/views/managed-web-contents-view.ts
5171
+ import { WebContentsView as WebContentsView5 } from "electron";
5172
+ function createManagedWebContentsView(opts) {
5173
+ let view = null;
5174
+ let preloadOverride = null;
5175
+ let runtimeAcquired = false;
5176
+ function liveWebContents2() {
5177
+ const wc = view?.webContents;
5026
5178
  if (!wc || wc.isDestroyed()) return null;
5027
5179
  return wc;
5028
5180
  }
5029
- function ensureHostToolbarView() {
5030
- if (hostToolbarView && liveHostToolbarWebContents()) {
5031
- return hostToolbarView;
5181
+ function teardown(current, detail) {
5182
+ if (view !== current) return;
5183
+ console.error(`[${opts.viewId}] ${detail} \u2014 destroying so the next ensureView() rebuilds`);
5184
+ view = null;
5185
+ opts.reconciler.destroyView(opts.viewId, current);
5186
+ opts.onBroken?.();
5187
+ }
5188
+ function ensureView() {
5189
+ if (view && liveWebContents2()) {
5190
+ return view;
5032
5191
  }
5033
- if (hostToolbarView) {
5034
- reconciler.destroyView(VIEW_ID.hostToolbar, hostToolbarView);
5192
+ if (view) {
5193
+ opts.reconciler.destroyView(opts.viewId, view);
5035
5194
  }
5036
- if (!hostToolbarRuntimeAcquired) {
5037
- acquireHostToolbarSessionRuntime();
5038
- hostToolbarRuntimeAcquired = true;
5195
+ if (!runtimeAcquired) {
5196
+ opts.sessionRuntime.acquire();
5197
+ runtimeAcquired = true;
5039
5198
  }
5040
5199
  const webPreferences = {
5041
5200
  nodeIntegration: false,
5042
5201
  contextIsolation: true,
5043
5202
  sandbox: false,
5044
- additionalArguments: [HOST_TOOLBAR_RUNTIME_MARKER]
5203
+ additionalArguments: [opts.marker]
5045
5204
  };
5046
- if (hostToolbarPreloadOverride !== null) {
5047
- webPreferences.preload = hostToolbarPreloadOverride;
5205
+ if (preloadOverride !== null) {
5206
+ webPreferences.preload = preloadOverride;
5048
5207
  }
5049
- const view = new WebContentsView5({ webPreferences });
5050
- hostToolbarView = view;
5051
- hostToolbarPort.attach(view.webContents);
5208
+ const next = new WebContentsView5({ webPreferences });
5209
+ view = next;
5210
+ opts.port.attach(next.webContents);
5052
5211
  try {
5053
- view.setBackgroundColor("#121212");
5212
+ next.setBackgroundColor("#121212");
5054
5213
  } catch {
5055
5214
  }
5056
5215
  try {
5057
- view.webContents.setWindowOpenHandler(({ url }) => handleWindowOpenExternal(url));
5216
+ next.webContents.setWindowOpenHandler(({ url }) => handleWindowOpenExternal(url));
5058
5217
  } catch {
5059
5218
  }
5060
- return view;
5061
- }
5062
- function notifyHostToolbarHeight(height) {
5063
- hostToolbarLastHeight = height;
5064
- ctx.notify.hostToolbarHeightChanged(height);
5065
- deps.reapplyPresentOverlays();
5066
- }
5067
- function setHostToolbarHeight(extent) {
5068
- if (hostToolbarHeightMode !== "auto") return;
5069
- notifyHostToolbarHeight(extent);
5070
- }
5071
- function hideHostToolbar() {
5072
- reconciler.setBaseDesired(VIEW_ID.hostToolbar, {
5073
- viewId: VIEW_ID.hostToolbar,
5074
- placement: { visible: false },
5075
- layer: VIEW_LAYER.hostToolbar
5219
+ next.webContents.on("did-fail-load", (_event, errorCode, _errorDescription, _validatedURL, isMainFrame) => {
5220
+ if (!isMainFrame || errorCode === -3) return;
5221
+ teardown(next, `did-fail-load (code ${errorCode})`);
5076
5222
  });
5077
- reconciler.reconcileNow();
5078
- notifyHostToolbarHeight(0);
5223
+ next.webContents.on("render-process-gone", (_event, details) => {
5224
+ teardown(next, `render-process-gone (${details.reason})`);
5225
+ });
5226
+ return next;
5079
5227
  }
5080
- const control = {
5228
+ return {
5081
5229
  async loadURL(url) {
5082
- const view = ensureHostToolbarView();
5083
- hostToolbarPort.invalidate();
5084
- await view.webContents.loadURL(url);
5230
+ const v = ensureView();
5231
+ opts.port.invalidate();
5232
+ await v.webContents.loadURL(url);
5085
5233
  },
5086
5234
  async loadFile(filePath) {
5087
- const view = ensureHostToolbarView();
5088
- hostToolbarPort.invalidate();
5089
- await view.webContents.loadFile(filePath);
5235
+ const v = ensureView();
5236
+ opts.port.invalidate();
5237
+ await v.webContents.loadFile(filePath);
5238
+ },
5239
+ liveWebContents: liveWebContents2,
5240
+ getView: () => view,
5241
+ setPreloadPath(path20) {
5242
+ preloadOverride = path20;
5243
+ },
5244
+ ensureView,
5245
+ dispose() {
5246
+ opts.port.dispose();
5247
+ opts.reconciler.destroyView(opts.viewId, view);
5248
+ view = null;
5249
+ if (runtimeAcquired) {
5250
+ opts.sessionRuntime.release();
5251
+ runtimeAcquired = false;
5252
+ }
5253
+ }
5254
+ };
5255
+ }
5256
+
5257
+ // src/main/services/views/host-slot-view.ts
5258
+ function deriveSlotControl(base, extra) {
5259
+ return {
5260
+ loadURL: (url) => base.loadURL(url),
5261
+ loadFile: (filePath) => base.loadFile(filePath),
5262
+ get webContents() {
5263
+ return base.webContents;
5090
5264
  },
5265
+ hide: () => base.hide(),
5266
+ setPreloadPath: (path20) => base.setPreloadPath(path20),
5267
+ onMessage: (channel, handler) => base.onMessage(channel, handler),
5268
+ onReady: (handler) => base.onReady(handler),
5269
+ send: (channel, payload) => base.send(channel, payload),
5270
+ ...extra
5271
+ };
5272
+ }
5273
+ function createHostSlotView(reconciler, config, deps) {
5274
+ let extentMode = "auto";
5275
+ let lastExtent = 0;
5276
+ let lastAdvertisedExtent = null;
5277
+ const port = config.portChannel;
5278
+ const managed = createManagedWebContentsView({
5279
+ reconciler,
5280
+ viewId: config.viewId,
5281
+ marker: config.marker,
5282
+ sessionRuntime: config.sessionRuntime,
5283
+ port
5284
+ });
5285
+ function notifyExtent(extent) {
5286
+ lastExtent = extent;
5287
+ deps.onExtentChanged(extent);
5288
+ deps.reapplyPresentOverlays?.();
5289
+ }
5290
+ function setExtent(extent) {
5291
+ lastAdvertisedExtent = extent;
5292
+ if (extentMode !== "auto") return;
5293
+ notifyExtent(extent);
5294
+ }
5295
+ function hideView() {
5296
+ reconciler.setBaseDesired(config.viewId, {
5297
+ viewId: config.viewId,
5298
+ placement: { visible: false },
5299
+ layer: config.layer
5300
+ });
5301
+ reconciler.reconcileNow();
5302
+ notifyExtent(0);
5303
+ lastAdvertisedExtent = null;
5304
+ }
5305
+ const control = {
5306
+ loadURL: (url) => managed.loadURL(url),
5307
+ loadFile: (filePath) => managed.loadFile(filePath),
5091
5308
  get webContents() {
5092
- return liveHostToolbarWebContents();
5309
+ return managed.liveWebContents();
5093
5310
  },
5094
5311
  hide() {
5095
- hideHostToolbar();
5096
- },
5097
- setPreloadPath(path20) {
5098
- hostToolbarPreloadOverride = path20;
5312
+ hideView();
5099
5313
  },
5100
- setHeightMode(mode) {
5314
+ setPreloadPath: (path20) => managed.setPreloadPath(path20),
5315
+ setExtentMode(mode) {
5101
5316
  if (mode !== "auto" && !(Number.isFinite(mode.fixed) && mode.fixed >= 0)) {
5102
5317
  throw new TypeError(
5103
- `hostToolbar.setHeightMode: fixed height must be a finite, non-negative number (got ${mode.fixed})`
5318
+ `${config.setExtentModeErrorLabel}: fixed extent must be a finite, non-negative number (got ${mode.fixed})`
5104
5319
  );
5105
5320
  }
5106
- hostToolbarHeightMode = mode;
5321
+ extentMode = mode;
5107
5322
  if (mode !== "auto") {
5108
- notifyHostToolbarHeight(mode.fixed);
5323
+ notifyExtent(mode.fixed);
5324
+ } else if (lastAdvertisedExtent !== null && lastAdvertisedExtent !== lastExtent) {
5325
+ notifyExtent(lastAdvertisedExtent);
5109
5326
  }
5110
5327
  },
5111
5328
  onMessage(channel, handler) {
5112
- return hostToolbarPort.onMessage(channel, handler);
5329
+ return port.onMessage(channel, handler);
5113
5330
  },
5114
5331
  onReady(handler) {
5115
- return hostToolbarPort.onReady(handler);
5332
+ return port.onReady(handler);
5116
5333
  },
5117
5334
  send(channel, payload) {
5118
- return hostToolbarPort.send(channel, payload);
5335
+ return port.send(channel, payload);
5119
5336
  }
5120
5337
  };
5121
- reconciler.registerView(VIEW_ID.hostToolbar, {
5122
- getView: () => hostToolbarView,
5123
- ensureView: () => ensureHostToolbarView(),
5338
+ reconciler.registerView(config.viewId, {
5339
+ getView: () => managed.getView(),
5340
+ ensureView: () => managed.ensureView(),
5124
5341
  ensureLazy: (desired) => {
5125
- if (desired?.placement.visible && !liveHostToolbarWebContents()) ensureHostToolbarView();
5342
+ if (desired?.placement.visible && !managed.liveWebContents()) managed.ensureView();
5343
+ }
5344
+ });
5345
+ return {
5346
+ control,
5347
+ setExtent,
5348
+ getExtent: () => lastExtent,
5349
+ getWebContentsId: () => managed.liveWebContents()?.id ?? null,
5350
+ dispose: () => managed.dispose()
5351
+ };
5352
+ }
5353
+
5354
+ // src/main/services/views/host-toolbar-view.ts
5355
+ function createHostToolbarView(ctx, reconciler, deps) {
5356
+ const port = createHostToolbarPortChannel({
5357
+ isCurrent: (wc) => slot.getWebContentsId() === wc.id
5358
+ });
5359
+ const slot = createHostSlotView(
5360
+ reconciler,
5361
+ {
5362
+ viewId: VIEW_ID.hostToolbar,
5363
+ layer: VIEW_LAYER.hostToolbar,
5364
+ marker: HOST_TOOLBAR_RUNTIME_MARKER,
5365
+ sessionRuntime: {
5366
+ acquire: acquireHostToolbarSessionRuntime,
5367
+ release: releaseHostToolbarSessionRuntime
5368
+ },
5369
+ portChannel: port,
5370
+ setExtentModeErrorLabel: "hostToolbar.setHeightMode"
5371
+ },
5372
+ {
5373
+ onExtentChanged: (height) => ctx.notify.hostToolbarHeightChanged(height),
5374
+ reapplyPresentOverlays: () => deps.reapplyPresentOverlays()
5375
+ }
5376
+ );
5377
+ const control = deriveSlotControl(slot.control, {
5378
+ setHeightMode: (mode) => slot.control.setExtentMode(mode)
5379
+ });
5380
+ return {
5381
+ control,
5382
+ setHostToolbarHeight: (extent) => slot.setExtent(extent),
5383
+ getHostToolbarHeight: () => slot.getExtent(),
5384
+ getHostToolbarWebContentsId: () => slot.getWebContentsId(),
5385
+ dispose: () => slot.dispose()
5386
+ };
5387
+ }
5388
+
5389
+ // src/main/services/views/host-sidebar-session-runtime.ts
5390
+ var runtime2 = createHostSlotSessionRuntime(hostSidebarRuntimePreloadPath);
5391
+ function acquireHostSidebarSessionRuntime() {
5392
+ runtime2.acquire();
5393
+ }
5394
+ function releaseHostSidebarSessionRuntime() {
5395
+ runtime2.release();
5396
+ }
5397
+
5398
+ // src/main/services/views/host-sidebar-port-channel.ts
5399
+ function createHostSidebarPortChannel(opts) {
5400
+ return createHostSlotPortChannel({
5401
+ isCurrent: opts.isCurrent,
5402
+ channel: ViewChannel.HostSidebarPort,
5403
+ logPrefix: "[host-sidebar]"
5404
+ });
5405
+ }
5406
+
5407
+ // src/main/services/views/host-sidebar-view.ts
5408
+ function createHostSidebarView(ctx, reconciler) {
5409
+ const port = createHostSidebarPortChannel({
5410
+ isCurrent: (wc) => slot.getWebContentsId() === wc.id
5411
+ });
5412
+ const slot = createHostSlotView(
5413
+ reconciler,
5414
+ {
5415
+ viewId: VIEW_ID.hostSidebar,
5416
+ layer: VIEW_LAYER.hostSidebar,
5417
+ marker: HOST_SIDEBAR_RUNTIME_MARKER,
5418
+ sessionRuntime: {
5419
+ acquire: acquireHostSidebarSessionRuntime,
5420
+ release: releaseHostSidebarSessionRuntime
5421
+ },
5422
+ portChannel: port,
5423
+ setExtentModeErrorLabel: "hostSidebar.setWidthMode"
5424
+ },
5425
+ {
5426
+ onExtentChanged: (width) => ctx.notify.hostSidebarWidthChanged(width)
5427
+ }
5428
+ );
5429
+ const control = deriveSlotControl(slot.control, {
5430
+ setWidthMode: (mode) => slot.control.setExtentMode(mode)
5431
+ });
5432
+ return {
5433
+ control,
5434
+ setHostSidebarWidth: (extent) => slot.setExtent(extent),
5435
+ getHostSidebarWidth: () => slot.getExtent(),
5436
+ getHostSidebarWebContentsId: () => slot.getWebContentsId(),
5437
+ dispose: () => slot.dispose()
5438
+ };
5439
+ }
5440
+
5441
+ // src/main/services/views/host-dialog-session-runtime.ts
5442
+ var runtime3 = createHostSlotSessionRuntime(hostDialogRuntimePreloadPath);
5443
+ function acquireHostDialogSessionRuntime() {
5444
+ runtime3.acquire();
5445
+ }
5446
+ function releaseHostDialogSessionRuntime() {
5447
+ runtime3.release();
5448
+ }
5449
+
5450
+ // src/main/services/views/host-dialog-port-channel.ts
5451
+ function createHostDialogPortChannel(opts) {
5452
+ return createHostSlotPortChannel({
5453
+ isCurrent: opts.isCurrent,
5454
+ channel: ViewChannel.HostDialogPort,
5455
+ logPrefix: "[host-dialog]"
5456
+ });
5457
+ }
5458
+
5459
+ // src/main/services/views/host-dialog-view.ts
5460
+ var DEFAULT_WIDTH = 480;
5461
+ var DEFAULT_HEIGHT = 320;
5462
+ function createHostDialogView(ctx, reconciler) {
5463
+ const port = createHostDialogPortChannel({
5464
+ isCurrent: (wc) => managed.liveWebContents()?.id === wc.id
5465
+ });
5466
+ let visible = false;
5467
+ let width = DEFAULT_WIDTH;
5468
+ let height = DEFAULT_HEIGHT;
5469
+ const managed = createManagedWebContentsView({
5470
+ reconciler,
5471
+ viewId: VIEW_ID.hostDialog,
5472
+ marker: HOST_DIALOG_RUNTIME_MARKER,
5473
+ sessionRuntime: {
5474
+ acquire: acquireHostDialogSessionRuntime,
5475
+ release: releaseHostDialogSessionRuntime
5476
+ },
5477
+ port,
5478
+ onBroken: () => {
5479
+ visible = false;
5480
+ reconciler.deleteOverlayDesired(VIEW_ID.hostDialog);
5126
5481
  }
5127
5482
  });
5128
- function dispose() {
5129
- hostToolbarPort.dispose();
5130
- reconciler.destroyView(VIEW_ID.hostToolbar, hostToolbarView);
5131
- hostToolbarView = null;
5132
- if (hostToolbarRuntimeAcquired) {
5133
- releaseHostToolbarSessionRuntime();
5134
- hostToolbarRuntimeAcquired = false;
5483
+ function computeBounds() {
5484
+ const [winW = 0, winH = 0] = ctx.windows.mainWindow.getContentSize();
5485
+ const w = Math.min(width, Math.max(1, winW));
5486
+ const h = Math.min(height, Math.max(1, winH));
5487
+ return {
5488
+ x: Math.max(0, Math.round((winW - w) / 2)),
5489
+ y: Math.max(0, Math.round((winH - h) / 2)),
5490
+ width: w,
5491
+ height: h
5492
+ };
5493
+ }
5494
+ function present() {
5495
+ reconciler.setOverlayDesired(VIEW_ID.hostDialog, {
5496
+ viewId: VIEW_ID.hostDialog,
5497
+ placement: { visible: true, bounds: computeBounds() },
5498
+ layer: VIEW_LAYER.hostDialog
5499
+ });
5500
+ reconciler.reconcileNow();
5501
+ }
5502
+ function reportMeasuredExtent(axis, extent) {
5503
+ if (!Number.isFinite(extent) || extent <= 0) return;
5504
+ if (axis === "inline") {
5505
+ width = extent;
5506
+ } else {
5507
+ height = extent;
5135
5508
  }
5509
+ if (visible) present();
5510
+ }
5511
+ function resetMeasuredExtent() {
5512
+ width = DEFAULT_WIDTH;
5513
+ height = DEFAULT_HEIGHT;
5514
+ if (visible) present();
5136
5515
  }
5516
+ const control = {
5517
+ loadURL: (url) => {
5518
+ resetMeasuredExtent();
5519
+ return managed.loadURL(url);
5520
+ },
5521
+ loadFile: (filePath) => {
5522
+ resetMeasuredExtent();
5523
+ return managed.loadFile(filePath);
5524
+ },
5525
+ get webContents() {
5526
+ return managed.liveWebContents();
5527
+ },
5528
+ setPreloadPath: (path20) => managed.setPreloadPath(path20),
5529
+ onMessage: (channel, handler) => port.onMessage(channel, handler),
5530
+ onReady: (handler) => port.onReady(handler),
5531
+ send: (channel, payload) => port.send(channel, payload),
5532
+ show() {
5533
+ managed.ensureView();
5534
+ visible = true;
5535
+ present();
5536
+ },
5537
+ hide() {
5538
+ visible = false;
5539
+ reconciler.deleteOverlayDesired(VIEW_ID.hostDialog);
5540
+ reconciler.reconcileNow();
5541
+ },
5542
+ isVisible: () => visible
5543
+ };
5544
+ reconciler.registerView(VIEW_ID.hostDialog, {
5545
+ getView: () => managed.getView(),
5546
+ ensureView: () => managed.ensureView()
5547
+ });
5137
5548
  return {
5138
5549
  control,
5139
- setHostToolbarHeight,
5140
- getHostToolbarHeight: () => hostToolbarLastHeight,
5141
- getHostToolbarWebContentsId: () => liveHostToolbarWebContents()?.id ?? null,
5142
- dispose
5550
+ reportMeasuredExtent,
5551
+ getHostDialogWebContentsId: () => managed.liveWebContents()?.id ?? null,
5552
+ reposition: () => {
5553
+ if (visible) present();
5554
+ },
5555
+ dispose: () => managed.dispose()
5143
5556
  };
5144
5557
  }
5145
5558
 
@@ -5272,6 +5685,44 @@ function createOverlayPanelsView(ctx, reconciler, deps) {
5272
5685
  pushData: (view, data) => ctx.notify.tooltipInit(view, data),
5273
5686
  readyMode: "manual"
5274
5687
  });
5688
+ function fullWindowBounds() {
5689
+ const [width = 0, height = 0] = ctx.windows.mainWindow.getContentSize();
5690
+ return { x: 0, y: 0, width: Math.max(1, width), height: Math.max(1, height) };
5691
+ }
5692
+ const projectCreateDialogPanel = createOverlayPanel({
5693
+ electron: { createWebContentsView: (opts) => new WebContentsView6(opts) },
5694
+ rendererDir: ctx.rendererDir,
5695
+ entry: "entries/project-create-dialog/index.html",
5696
+ webPreferences: {
5697
+ nodeIntegration: false,
5698
+ contextIsolation: true,
5699
+ sandbox: false,
5700
+ preload: mainPreloadPath
5701
+ },
5702
+ hardenNavigation: (wc) => applyNavigationHardening(wc, ctx.rendererDir),
5703
+ setDesired: overlayDesiredSetter(VIEW_ID.projectCreateDialog, VIEW_LAYER.dialog),
5704
+ registerView: (getView) => reconciler.registerView(VIEW_ID.projectCreateDialog, { getView }),
5705
+ destroyView: (view) => reconciler.destroyView(VIEW_ID.projectCreateDialog, view),
5706
+ pushData: (view, data) => ctx.notify.projectCreateInit(view, data),
5707
+ readyMode: "manual"
5708
+ });
5709
+ const updateDialogPanel = createOverlayPanel({
5710
+ electron: { createWebContentsView: (opts) => new WebContentsView6(opts) },
5711
+ rendererDir: ctx.rendererDir,
5712
+ entry: "entries/update-dialog/index.html",
5713
+ webPreferences: {
5714
+ nodeIntegration: false,
5715
+ contextIsolation: true,
5716
+ sandbox: false,
5717
+ preload: mainPreloadPath
5718
+ },
5719
+ hardenNavigation: (wc) => applyNavigationHardening(wc, ctx.rendererDir),
5720
+ setDesired: overlayDesiredSetter(VIEW_ID.updateDialog, VIEW_LAYER.dialog),
5721
+ registerView: (getView) => reconciler.registerView(VIEW_ID.updateDialog, { getView }),
5722
+ destroyView: (view) => reconciler.destroyView(VIEW_ID.updateDialog, view),
5723
+ pushData: (view, data) => ctx.notify.updateAvailable(view, data),
5724
+ readyMode: "manual"
5725
+ });
5275
5726
  let tooltipRequestId = 0;
5276
5727
  let activeTooltip = null;
5277
5728
  async function showSettings() {
@@ -5311,10 +5762,29 @@ function createOverlayPanelsView(ctx, reconciler, deps) {
5311
5762
  activeTooltip = null;
5312
5763
  tooltipPanel.hide();
5313
5764
  }
5765
+ function showProjectCreateDialog(data) {
5766
+ projectCreateDialogPanel.show(data, fullWindowBounds());
5767
+ }
5768
+ function hideProjectCreateDialog() {
5769
+ projectCreateDialogPanel.hide();
5770
+ }
5771
+ function showUpdateDialog(data) {
5772
+ updateDialogPanel.show(data, fullWindowBounds());
5773
+ }
5774
+ function hideUpdateDialog() {
5775
+ updateDialogPanel.hide();
5776
+ }
5777
+ function notifyUpdateDownloadProgress(percent) {
5778
+ const wc = updateDialogPanel.getWebContents();
5779
+ if (!wc) return;
5780
+ wc.send(UpdateChannel.DownloadProgress, { percent });
5781
+ }
5314
5782
  function markOverlayReady(webContentsId) {
5315
5783
  settingsPanel.markReady(webContentsId);
5316
5784
  popoverPanel.markReady(webContentsId);
5317
5785
  tooltipPanel.markReady(webContentsId);
5786
+ projectCreateDialogPanel.markReady(webContentsId);
5787
+ updateDialogPanel.markReady(webContentsId);
5318
5788
  }
5319
5789
  function applyTooltipMeasurement(webContentsId, measurement) {
5320
5790
  const active = activeTooltip;
@@ -5324,20 +5794,36 @@ function createOverlayPanelsView(ctx, reconciler, deps) {
5324
5794
  tooltipPanel.reposition(computeTooltipBounds(active.anchor, w, h, measurement));
5325
5795
  }
5326
5796
  function reapplyPresentOverlays() {
5327
- if (settingsPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.settings)) void showSettings();
5797
+ if (settingsPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.settings)) {
5798
+ showSettings().catch(() => {
5799
+ });
5800
+ }
5328
5801
  if (popoverPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.popover)) {
5329
5802
  const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
5330
5803
  popoverPanel.reposition(computePopoverBounds(w, h, overlayHeaderHeight()));
5331
5804
  }
5805
+ if (projectCreateDialogPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.projectCreateDialog)) {
5806
+ projectCreateDialogPanel.reposition(fullWindowBounds());
5807
+ }
5808
+ if (updateDialogPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.updateDialog)) {
5809
+ updateDialogPanel.reposition(fullWindowBounds());
5810
+ }
5332
5811
  }
5333
5812
  function applySettingsBoundsIfPresent() {
5334
- if (settingsPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.settings)) void showSettings();
5813
+ if (settingsPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.settings)) {
5814
+ showSettings().catch(() => {
5815
+ });
5816
+ }
5335
5817
  }
5336
5818
  function destroySettings() {
5337
5819
  activeTooltip = null;
5338
5820
  settingsPanel.destroy();
5339
5821
  tooltipPanel.destroy();
5340
5822
  }
5823
+ function destroyDialogs() {
5824
+ projectCreateDialogPanel.destroy();
5825
+ updateDialogPanel.destroy();
5826
+ }
5341
5827
  return {
5342
5828
  showSettings,
5343
5829
  hideSettings,
@@ -5348,13 +5834,21 @@ function createOverlayPanelsView(ctx, reconciler, deps) {
5348
5834
  hideTooltip,
5349
5835
  markOverlayReady,
5350
5836
  applyTooltipMeasurement,
5837
+ showProjectCreateDialog,
5838
+ hideProjectCreateDialog,
5839
+ showUpdateDialog,
5840
+ hideUpdateDialog,
5841
+ notifyUpdateDownloadProgress,
5351
5842
  reapplyPresentOverlays,
5352
5843
  applySettingsBoundsIfPresent,
5353
5844
  destroySettings,
5845
+ destroyDialogs,
5354
5846
  getSettingsWebContents: () => settingsPanel.getWebContents(),
5355
5847
  getSettingsWebContentsId: () => settingsPanel.getWebContentsId(),
5356
5848
  getPopoverWebContentsId: () => popoverPanel.getWebContentsId(),
5357
- getTooltipWebContentsId: () => tooltipPanel.getWebContentsId()
5849
+ getTooltipWebContentsId: () => tooltipPanel.getWebContentsId(),
5850
+ getProjectCreateDialogWebContentsId: () => projectCreateDialogPanel.getWebContentsId(),
5851
+ getUpdateDialogWebContentsId: () => updateDialogPanel.getWebContentsId()
5358
5852
  };
5359
5853
  }
5360
5854
 
@@ -5693,6 +6187,8 @@ function createViewManager(ctx) {
5693
6187
  const hostToolbar = createHostToolbarView(ctx, reconciler, {
5694
6188
  reapplyPresentOverlays: () => reapplyToolbarDependentOverlays()
5695
6189
  });
6190
+ const hostSidebar = createHostSidebarView(ctx, reconciler);
6191
+ const hostDialog = createHostDialogView(ctx, reconciler);
5696
6192
  const overlayPanels = createOverlayPanelsView(ctx, reconciler, {
5697
6193
  getHostToolbarHeight: hostToolbar.getHostToolbarHeight
5698
6194
  });
@@ -5713,6 +6209,9 @@ function createViewManager(ctx) {
5713
6209
  workbench.cancelWorkbenchAttachHold();
5714
6210
  disposeProjectViews();
5715
6211
  hostToolbar.dispose();
6212
+ hostSidebar.dispose();
6213
+ hostDialog.dispose();
6214
+ overlayPanels.destroyDialogs();
5716
6215
  }
5717
6216
  return {
5718
6217
  attachNativeSimulator: nativeSimulator.attachNativeSimulator,
@@ -5729,7 +6228,17 @@ function createViewManager(ctx) {
5729
6228
  hideTooltip: overlayPanels.hideTooltip,
5730
6229
  markOverlayReady: overlayPanels.markOverlayReady,
5731
6230
  applyTooltipMeasurement: overlayPanels.applyTooltipMeasurement,
5732
- repositionAll: () => overlayPanels.reapplyPresentOverlays(),
6231
+ showProjectCreateDialog: overlayPanels.showProjectCreateDialog,
6232
+ hideProjectCreateDialog: overlayPanels.hideProjectCreateDialog,
6233
+ showUpdateDialog: overlayPanels.showUpdateDialog,
6234
+ hideUpdateDialog: overlayPanels.hideUpdateDialog,
6235
+ notifyUpdateDownloadProgress: overlayPanels.notifyUpdateDownloadProgress,
6236
+ getProjectCreateDialogWebContentsId: overlayPanels.getProjectCreateDialogWebContentsId,
6237
+ getUpdateDialogWebContentsId: overlayPanels.getUpdateDialogWebContentsId,
6238
+ repositionAll: () => {
6239
+ overlayPanels.reapplyPresentOverlays();
6240
+ hostDialog.reposition();
6241
+ },
5733
6242
  disposeProjectViews,
5734
6243
  disposeAll,
5735
6244
  getSimulatorWebContentsId: nativeSimulator.getSimulatorWebContentsId,
@@ -5743,6 +6252,7 @@ function createViewManager(ctx) {
5743
6252
  getHostToolbarHeight: hostToolbar.getHostToolbarHeight,
5744
6253
  resize: () => overlayPanels.applySettingsBoundsIfPresent(),
5745
6254
  setPlacementSnapshot: reconciler.setPlacementSnapshot,
6255
+ allocatePlacementGeneration: reconciler.allocateGeneration,
5746
6256
  attachWorkbench: workbench.attachWorkbench,
5747
6257
  setWorkbenchSource: workbench.setWorkbenchSource,
5748
6258
  detachWorkbench: workbench.detachWorkbench,
@@ -5750,7 +6260,14 @@ function createViewManager(ctx) {
5750
6260
  holdWorkbenchAttach: workbench.holdWorkbenchAttach,
5751
6261
  cancelWorkbenchAttachHold: workbench.cancelWorkbenchAttachHold,
5752
6262
  setHostToolbarHeight: hostToolbar.setHostToolbarHeight,
5753
- hostToolbar: hostToolbar.control
6263
+ hostToolbar: hostToolbar.control,
6264
+ getHostSidebarWebContentsId: hostSidebar.getHostSidebarWebContentsId,
6265
+ getHostSidebarWidth: hostSidebar.getHostSidebarWidth,
6266
+ setHostSidebarWidth: hostSidebar.setHostSidebarWidth,
6267
+ hostSidebar: hostSidebar.control,
6268
+ getHostDialogWebContentsId: hostDialog.getHostDialogWebContentsId,
6269
+ reportHostDialogMeasuredExtent: hostDialog.reportMeasuredExtent,
6270
+ hostDialog: hostDialog.control
5754
6271
  };
5755
6272
  }
5756
6273
 
@@ -5878,6 +6395,7 @@ __export(project_repository_exports, {
5878
6395
  removeProject: () => removeProject,
5879
6396
  saveCompileConfig: () => saveCompileConfig,
5880
6397
  updateLastOpened: () => updateLastOpened,
6398
+ updateProject: () => updateProject,
5881
6399
  updateProjectSettings: () => updateProjectSettings,
5882
6400
  validateProjectDir: () => validateProjectDir
5883
6401
  });
@@ -5885,6 +6403,53 @@ import { app as app6 } from "electron";
5885
6403
  import path9 from "path";
5886
6404
  import fs5 from "fs";
5887
6405
  var log2 = createLogger("projects");
6406
+ function readProjectConfig(dirPath) {
6407
+ let merged = {};
6408
+ for (const fileName of ["project.config.json", "project.private.config.json"]) {
6409
+ const configPath = path9.join(dirPath, fileName);
6410
+ if (!fs5.existsSync(configPath)) continue;
6411
+ try {
6412
+ merged = { ...merged, ...JSON.parse(fs5.readFileSync(configPath, "utf-8")) };
6413
+ } catch (err2) {
6414
+ log2.warn(`Failed to parse ${configPath}`, err2);
6415
+ }
6416
+ }
6417
+ return merged;
6418
+ }
6419
+ function readProjectName(dirPath) {
6420
+ const raw = readProjectConfig(dirPath).projectname;
6421
+ if (typeof raw !== "string" || !raw.trim()) return null;
6422
+ try {
6423
+ return decodeURIComponent(raw);
6424
+ } catch {
6425
+ return raw;
6426
+ }
6427
+ }
6428
+ function writeProjectName(dirPath, name) {
6429
+ const configPath = path9.join(dirPath, "project.private.config.json");
6430
+ let config = {};
6431
+ if (fs5.existsSync(configPath)) {
6432
+ try {
6433
+ config = JSON.parse(fs5.readFileSync(configPath, "utf-8"));
6434
+ } catch {
6435
+ throw new Error(`\u65E0\u6CD5\u91CD\u547D\u540D\uFF1A${configPath} \u4E0D\u662F\u5408\u6CD5 JSON`);
6436
+ }
6437
+ }
6438
+ fs5.writeFileSync(
6439
+ configPath,
6440
+ JSON.stringify({ ...config, projectname: encodeURIComponent(name) }, null, 2)
6441
+ );
6442
+ }
6443
+ function detectRuntimeType(dirPath) {
6444
+ const compileType = readProjectConfig(dirPath).compileType;
6445
+ if (compileType === "game") return "minigame";
6446
+ if (compileType === "miniprogram") return "miniprogram";
6447
+ const hasMiniProgramConfig = fs5.existsSync(path9.join(dirPath, "app.json"));
6448
+ const hasMiniGameConfig = fs5.existsSync(path9.join(dirPath, "game.json"));
6449
+ const hasMiniGameEntry = ["game.js", "game.ts"].some((fileName) => fs5.existsSync(path9.join(dirPath, fileName)));
6450
+ if (!hasMiniProgramConfig && hasMiniGameConfig && hasMiniGameEntry) return "minigame";
6451
+ return "miniprogram";
6452
+ }
5888
6453
  function getProjectsFile() {
5889
6454
  return path9.join(app6.getPath("userData"), "dimina-projects.json");
5890
6455
  }
@@ -5908,6 +6473,12 @@ function validateProjectDir(dirPath) {
5908
6473
  if (!fs5.existsSync(dirPath)) {
5909
6474
  return `\u5C0F\u7A0B\u5E8F\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${dirPath}`;
5910
6475
  }
6476
+ if (detectRuntimeType(dirPath) === "minigame") {
6477
+ if (!fs5.existsSync(path9.join(dirPath, "game.json"))) {
6478
+ return "\u8BE5\u76EE\u5F55\u7F3A\u5C11 game.json\uFF0C\u8BF7\u9009\u62E9\u5305\u542B\u5C0F\u6E38\u620F\u6E90\u7801\u7684\u76EE\u5F55";
6479
+ }
6480
+ return null;
6481
+ }
5911
6482
  if (!fs5.existsSync(path9.join(dirPath, "app.json"))) {
5912
6483
  const configPath = path9.join(dirPath, "project.config.json");
5913
6484
  if (fs5.existsSync(configPath)) {
@@ -5930,20 +6501,12 @@ function hasProject(dirPath) {
5930
6501
  }
5931
6502
  function addProject(dirPath) {
5932
6503
  const projects = load();
5933
- let name = path9.basename(dirPath);
5934
- try {
5935
- const configPath = path9.join(dirPath, "project.config.json");
5936
- if (fs5.existsSync(configPath)) {
5937
- const cfg = JSON.parse(fs5.readFileSync(configPath, "utf-8"));
5938
- if (cfg.projectname) name = cfg.projectname;
5939
- }
5940
- } catch (err2) {
5941
- log2.warn("Failed to read project name from config", err2);
5942
- }
5943
- const project = { name, path: dirPath, lastOpened: null };
6504
+ const name = readProjectName(dirPath) ?? path9.basename(dirPath);
6505
+ const type = detectRuntimeType(dirPath);
6506
+ const project = { name, path: dirPath, lastOpened: null, type };
5944
6507
  const idx = projects.findIndex((p) => p.path === dirPath);
5945
6508
  if (idx >= 0) {
5946
- projects[idx] = { ...projects[idx], name };
6509
+ projects[idx] = { ...projects[idx], name, type };
5947
6510
  } else {
5948
6511
  projects.unshift(project);
5949
6512
  }
@@ -5953,6 +6516,26 @@ function addProject(dirPath) {
5953
6516
  function removeProject(dirPath) {
5954
6517
  save(load().filter((p) => p.path !== dirPath));
5955
6518
  }
6519
+ function updateProject(dirPath, patch) {
6520
+ const projects = load();
6521
+ const idx = projects.findIndex((p) => p.path === dirPath);
6522
+ if (idx < 0) return null;
6523
+ const next = { ...projects[idx] };
6524
+ if (patch.name !== void 0) {
6525
+ const name = patch.name.trim();
6526
+ if (!name) throw new Error("Project name cannot be empty");
6527
+ next.name = name;
6528
+ }
6529
+ if (patch.iconUrl !== void 0) {
6530
+ const iconUrl = patch.iconUrl.trim();
6531
+ if (iconUrl) next.iconUrl = iconUrl;
6532
+ else delete next.iconUrl;
6533
+ }
6534
+ if (next.name !== projects[idx].name) writeProjectName(dirPath, next.name);
6535
+ projects[idx] = next;
6536
+ save(projects);
6537
+ return next;
6538
+ }
5956
6539
  function updateLastOpened(dirPath) {
5957
6540
  const projects = load();
5958
6541
  const idx = projects.findIndex((p) => p.path === dirPath);
@@ -5964,13 +6547,17 @@ function updateLastOpened(dirPath) {
5964
6547
  function getCompileConfig(dirPath) {
5965
6548
  const projects = load();
5966
6549
  const project = projects.find((p) => p.path === dirPath);
5967
- return project?.compileConfig ?? {
5968
- startPage: "",
6550
+ if (project?.compileConfig) return project.compileConfig;
6551
+ return {
6552
+ startPage: getProjectPages(dirPath).entryPagePath,
5969
6553
  scene: DEFAULT_SCENE,
5970
6554
  queryParams: []
5971
6555
  };
5972
6556
  }
5973
6557
  function getProjectPages(dirPath) {
6558
+ if (detectRuntimeType(dirPath) === "minigame") {
6559
+ return { pages: ["game"], entryPagePath: "game" };
6560
+ }
5974
6561
  const appJsonPath = path9.join(dirPath, "app.json");
5975
6562
  try {
5976
6563
  const appJson = JSON.parse(
@@ -6178,6 +6765,15 @@ function createWorkspaceService(ctx) {
6178
6765
  removeProject: async (dirPath) => {
6179
6766
  await provider.removeProject(dirPath);
6180
6767
  },
6768
+ updateProject: async (dirPath, patch) => {
6769
+ const projects = await provider.listProjects();
6770
+ const existing = projects.find((p) => p.path === dirPath);
6771
+ if (!existing) throw new Error(`No such project: ${dirPath}`);
6772
+ if (!provider.updateProject) {
6773
+ throw new Error("\u5F53\u524D\u5BBF\u4E3B\u4E0D\u652F\u6301\u7F16\u8F91\u9879\u76EE");
6774
+ }
6775
+ return provider.updateProject(dirPath, patch);
6776
+ },
6181
6777
  hasProject: async (dirPath) => {
6182
6778
  const projects = await provider.listProjects();
6183
6779
  return projects.some((p) => p.path === dirPath);
@@ -6348,6 +6944,11 @@ function createLocalProjectsProvider() {
6348
6944
  listProjects: () => listProjects(),
6349
6945
  addProject: (dirPath) => addProject(dirPath),
6350
6946
  removeProject: (dirPath) => removeProject(dirPath),
6947
+ updateProject: (dirPath, patch) => {
6948
+ const updated = updateProject(dirPath, patch);
6949
+ if (!updated) throw new Error(`No such project: ${dirPath}`);
6950
+ return updated;
6951
+ },
6351
6952
  validateProjectDir: (dirPath) => validateProjectDir(dirPath),
6352
6953
  updateLastOpened: (dirPath) => updateLastOpened(dirPath),
6353
6954
  getCompileConfig: (dirPath) => getCompileConfig(dirPath),
@@ -6620,6 +7221,7 @@ function createWorkbenchContext(opts) {
6620
7221
  opts.builtinTemplates ?? "all"
6621
7222
  );
6622
7223
  ctx.customCreateProjectDialog = opts.customCreateProjectDialog;
7224
+ ctx.customEditProjectDialog = opts.customEditProjectDialog;
6623
7225
  ctx.onBeforeOpenProject = opts.onBeforeOpenProject;
6624
7226
  ctx.workspace = createWorkspaceService(ctx);
6625
7227
  ctx.senderPolicy = createWorkbenchSenderPolicy(ctx);
@@ -6800,6 +7402,19 @@ var TooltipMeasuredSchema = z3.tuple([
6800
7402
  height: z3.number().finite().positive()
6801
7403
  })
6802
7404
  ]);
7405
+ var ProjectCreateShowSchema = z3.tuple([
7406
+ z3.object({
7407
+ templates: z3.array(z3.looseObject({})),
7408
+ defaultBaseDir: z3.string()
7409
+ })
7410
+ ]);
7411
+ var ProjectCreateSubmitSchema = z3.tuple([
7412
+ z3.object({
7413
+ name: z3.string().min(1),
7414
+ path: AbsolutePath,
7415
+ templateId: z3.string().min(1)
7416
+ })
7417
+ ]);
6803
7418
  var SimWidth = z3.number().int().min(100).max(2e3);
6804
7419
  var SimulatorAttachNativeSchema = z3.tuple([
6805
7420
  z3.string().url().refine((u) => u.startsWith("http://") || u.startsWith("https://"), {
@@ -6865,13 +7480,33 @@ var HostToolbarAdvertiseHeightSchema = z3.tuple([
6865
7480
  extent: NonNegInt
6866
7481
  })
6867
7482
  ]);
7483
+ var HostSidebarAdvertiseWidthSchema = z3.tuple([
7484
+ z3.object({
7485
+ axis: z3.literal("inline"),
7486
+ extent: NonNegInt
7487
+ })
7488
+ ]);
7489
+ var HostDialogAdvertiseSizeSchema = z3.tuple([
7490
+ z3.object({
7491
+ axis: z3.union([z3.literal("block"), z3.literal("inline")]),
7492
+ extent: NonNegInt
7493
+ })
7494
+ ]);
6868
7495
  var SimulatorCustomApiInvokeSchema = z3.tuple([
6869
7496
  z3.string().min(1).max(256),
6870
7497
  z3.unknown()
6871
7498
  ]);
6872
7499
  var ProjectGetPagesSchema = z3.tuple([AbsolutePath]);
6873
7500
  var ProjectGetCompileConfigSchema = z3.tuple([AbsolutePath]);
7501
+ var ProjectsUpdateSchema = z3.tuple([
7502
+ AbsolutePath,
7503
+ z3.object({
7504
+ name: z3.string().min(1).max(200).optional(),
7505
+ iconUrl: z3.string().max(2048).optional()
7506
+ })
7507
+ ]);
6874
7508
  var ProjectsRemoveSchema = z3.tuple([AbsolutePath]);
7509
+ var ProjectsOpenEditDialogSchema = z3.tuple([AbsolutePath]);
6875
7510
  var WorkbenchSettingsSaveSchema = z3.tuple([
6876
7511
  z3.looseObject({
6877
7512
  cdp: z3.looseObject({
@@ -6968,6 +7603,20 @@ function registerTooltipIpc(ctx) {
6968
7603
  });
6969
7604
  }
6970
7605
 
7606
+ // src/main/ipc/project-create.ts
7607
+ function registerProjectCreateIpc(ctx) {
7608
+ return new IpcRegistry(ctx.senderPolicy).on(ProjectCreateChannel.Show, (_event, ...args) => {
7609
+ const [data] = validate(ProjectCreateChannel.Show, ProjectCreateShowSchema, args);
7610
+ ctx.views.showProjectCreateDialog(data);
7611
+ }).on(ProjectCreateChannel.Cancel, () => {
7612
+ ctx.views.hideProjectCreateDialog();
7613
+ }).on(ProjectCreateChannel.Submit, (_event, ...args) => {
7614
+ const [input] = validate(ProjectCreateChannel.Submit, ProjectCreateSubmitSchema, args);
7615
+ ctx.views.hideProjectCreateDialog();
7616
+ ctx.notify.projectCreateSubmitted(input);
7617
+ });
7618
+ }
7619
+
6971
7620
  // src/main/ipc/projects.ts
6972
7621
  import { app as app8, dialog } from "electron";
6973
7622
  import path13 from "path";
@@ -7039,7 +7688,7 @@ function writeProjectConfig(target, name) {
7039
7688
  cfg = {};
7040
7689
  }
7041
7690
  }
7042
- cfg.projectname = name;
7691
+ cfg.projectname = encodeURIComponent(name);
7043
7692
  fs7.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
7044
7693
  }
7045
7694
  async function createProject(input, ctx) {
@@ -7087,10 +7736,20 @@ function registerProjectsIpc(ctx) {
7087
7736
  buttons: ["\u786E\u5B9A"]
7088
7737
  });
7089
7738
  }
7739
+ const importedCategory = project.type ?? "miniprogram";
7740
+ ctx.notify.hostSidebarCategorySelected(importedCategory);
7741
+ ctx.views.hostSidebar.send("project-category-forced", { category: importedCategory });
7090
7742
  return project;
7091
7743
  }).handle(ProjectsChannel.Remove, (_event, ...args) => {
7092
7744
  const [dirPath] = validate(ProjectsChannel.Remove, ProjectsRemoveSchema, args);
7093
7745
  return ctx.workspace.removeProject(dirPath);
7746
+ }).handle(ProjectsChannel.Update, (_event, ...args) => {
7747
+ const [dirPath, patch] = validate(
7748
+ ProjectsChannel.Update,
7749
+ ProjectsUpdateSchema,
7750
+ args
7751
+ );
7752
+ return ctx.workspace.updateProject(dirPath, patch);
7094
7753
  }).handle(ProjectsChannel.ListTemplates, () => {
7095
7754
  return sanitizeTemplates(ctx.projectTemplates ?? []);
7096
7755
  }).handle(ProjectsChannel.OpenCreateDialog, async () => {
@@ -7100,6 +7759,20 @@ function registerProjectsIpc(ctx) {
7100
7759
  parentWindow: ctx.windows.mainWindow,
7101
7760
  templates: sanitized
7102
7761
  });
7762
+ }).handle(ProjectsChannel.OpenEditDialog, async (_event, ...args) => {
7763
+ if (!ctx.customEditProjectDialog) return null;
7764
+ const [dirPath] = validate(
7765
+ ProjectsChannel.OpenEditDialog,
7766
+ ProjectsOpenEditDialogSchema,
7767
+ args
7768
+ );
7769
+ const project = (await ctx.workspace.listProjects()).find((p) => p.path === dirPath);
7770
+ if (!project) throw new Error(`No such project: ${dirPath}`);
7771
+ const result = await ctx.customEditProjectDialog({
7772
+ parentWindow: ctx.windows.mainWindow,
7773
+ project
7774
+ });
7775
+ return { result };
7103
7776
  }).handle(ProjectsChannel.Create, async (_event, ...args) => {
7104
7777
  const [raw] = args;
7105
7778
  if (!raw || typeof raw !== "object") {
@@ -7253,13 +7926,13 @@ function registerSettingsIpc(ctx) {
7253
7926
  };
7254
7927
  }).handle(WorkbenchSettingsChannel.GetMcpStatus, () => {
7255
7928
  const settings = loadWorkbenchSettings();
7256
- const runtime = getMcpStatus();
7929
+ const runtime4 = getMcpStatus();
7257
7930
  return {
7258
7931
  configured: settings.mcp.enabled,
7259
7932
  configuredPort: settings.mcp.port,
7260
- running: runtime.running,
7261
- activePort: runtime.port,
7262
- error: runtime.error
7933
+ running: runtime4.running,
7934
+ activePort: runtime4.port,
7935
+ error: runtime4.error
7263
7936
  };
7264
7937
  }).handle(SettingsChannel.SetVisible, async (_, ...args) => {
7265
7938
  const [visible] = validate(SettingsChannel.SetVisible, SettingsSetVisibleSchema, args);
@@ -7307,6 +7980,76 @@ function registerInternalDevtoolsIpc(ctx) {
7307
7980
  });
7308
7981
  }
7309
7982
 
7983
+ // src/main/ipc/views.ts
7984
+ import { ipcMain as ipcMain3 } from "electron";
7985
+ function registerViewsIpc(ctx) {
7986
+ const registry = new IpcRegistry(ctx.senderPolicy).handle(ViewChannel.AllocatePlacementGeneration, () => ctx.views.allocatePlacementGeneration()).handle(ViewChannel.PlacementSnapshot, (_event, ...args) => {
7987
+ const [snapshot] = validate(
7988
+ ViewChannel.PlacementSnapshot,
7989
+ PlacementSnapshotSchema,
7990
+ args
7991
+ );
7992
+ ctx.views.setPlacementSnapshot(snapshot);
7993
+ }).handle(ViewChannel.HostToolbarGetHeight, () => ctx.views.getHostToolbarHeight()).handle(ViewChannel.HostSidebarGetWidth, () => ctx.views.getHostSidebarWidth());
7994
+ const onAdvertiseHeight = (event, ...args) => {
7995
+ if (event.sender.id !== ctx.views.getHostToolbarWebContentsId()) return;
7996
+ let extent;
7997
+ try {
7998
+ ;
7999
+ [{ extent }] = validate(
8000
+ ViewChannel.HostToolbarAdvertiseHeight,
8001
+ HostToolbarAdvertiseHeightSchema,
8002
+ args
8003
+ );
8004
+ } catch {
8005
+ return;
8006
+ }
8007
+ ctx.views.setHostToolbarHeight(extent);
8008
+ };
8009
+ ipcMain3.on(ViewChannel.HostToolbarAdvertiseHeight, onAdvertiseHeight);
8010
+ const onAdvertiseWidth = (event, ...args) => {
8011
+ if (event.sender.id !== ctx.views.getHostSidebarWebContentsId()) return;
8012
+ let extent;
8013
+ try {
8014
+ ;
8015
+ [{ extent }] = validate(
8016
+ ViewChannel.HostSidebarAdvertiseWidth,
8017
+ HostSidebarAdvertiseWidthSchema,
8018
+ args
8019
+ );
8020
+ } catch {
8021
+ return;
8022
+ }
8023
+ ctx.views.setHostSidebarWidth(extent);
8024
+ };
8025
+ ipcMain3.on(ViewChannel.HostSidebarAdvertiseWidth, onAdvertiseWidth);
8026
+ const onAdvertiseDialogSize = (event, ...args) => {
8027
+ if (event.sender.id !== ctx.views.getHostDialogWebContentsId()) return;
8028
+ let axis;
8029
+ let extent;
8030
+ try {
8031
+ ;
8032
+ [{ axis, extent }] = validate(
8033
+ ViewChannel.HostDialogAdvertiseSize,
8034
+ HostDialogAdvertiseSizeSchema,
8035
+ args
8036
+ );
8037
+ } catch {
8038
+ return;
8039
+ }
8040
+ ctx.views.reportHostDialogMeasuredExtent(axis, extent);
8041
+ };
8042
+ ipcMain3.on(ViewChannel.HostDialogAdvertiseSize, onAdvertiseDialogSize);
8043
+ return {
8044
+ dispose() {
8045
+ void registry.dispose();
8046
+ ipcMain3.removeListener(ViewChannel.HostToolbarAdvertiseHeight, onAdvertiseHeight);
8047
+ ipcMain3.removeListener(ViewChannel.HostSidebarAdvertiseWidth, onAdvertiseWidth);
8048
+ ipcMain3.removeListener(ViewChannel.HostDialogAdvertiseSize, onAdvertiseDialogSize);
8049
+ }
8050
+ };
8051
+ }
8052
+
7310
8053
  // src/main/ipc/simulator-module.ts
7311
8054
  import { DisposableRegistry as DisposableRegistry3 } from "@dimina-kit/electron-deck/main";
7312
8055
 
@@ -7341,47 +8084,11 @@ function installBridgeRouter(ctx) {
7341
8084
  installRuntimeBridgeRouter(ctx);
7342
8085
  }
7343
8086
 
7344
- // src/main/ipc/views.ts
7345
- import { ipcMain as ipcMain3 } from "electron";
7346
- function registerViewsIpc(ctx) {
7347
- const registry = new IpcRegistry(ctx.senderPolicy).handle(ViewChannel.PlacementSnapshot, (_event, ...args) => {
7348
- const [snapshot] = validate(
7349
- ViewChannel.PlacementSnapshot,
7350
- PlacementSnapshotSchema,
7351
- args
7352
- );
7353
- ctx.views.setPlacementSnapshot(snapshot);
7354
- }).handle(ViewChannel.HostToolbarGetHeight, () => ctx.views.getHostToolbarHeight());
7355
- const onAdvertiseHeight = (event, ...args) => {
7356
- if (event.sender.id !== ctx.views.getHostToolbarWebContentsId()) return;
7357
- let extent;
7358
- try {
7359
- ;
7360
- [{ extent }] = validate(
7361
- ViewChannel.HostToolbarAdvertiseHeight,
7362
- HostToolbarAdvertiseHeightSchema,
7363
- args
7364
- );
7365
- } catch {
7366
- return;
7367
- }
7368
- ctx.views.setHostToolbarHeight(extent);
7369
- };
7370
- ipcMain3.on(ViewChannel.HostToolbarAdvertiseHeight, onAdvertiseHeight);
7371
- return {
7372
- dispose() {
7373
- void registry.dispose();
7374
- ipcMain3.removeListener(ViewChannel.HostToolbarAdvertiseHeight, onAdvertiseHeight);
7375
- }
7376
- };
7377
- }
7378
-
7379
8087
  // src/main/ipc/simulator-module.ts
7380
8088
  var simulatorModule = {
7381
8089
  setup: (ctx) => {
7382
8090
  const reg = new DisposableRegistry3();
7383
8091
  reg.add(registerSimulatorIpc(ctx));
7384
- reg.add(registerViewsIpc(ctx));
7385
8092
  installBridgeRouter(ctx);
7386
8093
  return reg;
7387
8094
  }
@@ -10025,7 +10732,9 @@ async function startWorkbenchCoiServer(options) {
10025
10732
  import { app as app11, shell as shell3 } from "electron";
10026
10733
  var UpdateManager = class {
10027
10734
  checker;
10028
- mainWindow;
10735
+ showUpdatePanel;
10736
+ notifyDownloadProgress;
10737
+ hideUpdatePanel;
10029
10738
  getCurrentVersion;
10030
10739
  latestUpdate = null;
10031
10740
  downloadedPath = null;
@@ -10042,16 +10751,26 @@ var UpdateManager = class {
10042
10751
  timer = null;
10043
10752
  initialTimer = null;
10044
10753
  ipc;
10754
+ /**
10755
+ * Set by `dispose()`. Clearing the timers only stops FUTURE ticks — an
10756
+ * in-flight `checkAndNotify()` invocation (already past its `await
10757
+ * this.check()`) has no timer left to cancel it, and would otherwise call
10758
+ * `showUpdatePanel` after dispose has torn down the overlay panel that
10759
+ * owns (e.g. `views.disposeAll()` destroying its WebContentsView).
10760
+ */
10761
+ disposed = false;
10045
10762
  constructor(opts) {
10046
10763
  this.checker = opts.checker;
10047
- this.mainWindow = opts.mainWindow;
10764
+ this.showUpdatePanel = opts.showUpdatePanel;
10765
+ this.notifyDownloadProgress = opts.notifyDownloadProgress;
10766
+ this.hideUpdatePanel = opts.hideUpdatePanel;
10048
10767
  this.getCurrentVersion = opts.getCurrentVersion ?? (() => app11.getVersion());
10049
10768
  this.ipc = new IpcRegistry(opts.senderPolicy);
10050
10769
  this.registerIpc();
10051
10770
  this.startPeriodicCheck(opts.checkInterval ?? 60 * 60 * 1e3, opts.initialDelay ?? 5e3);
10052
10771
  }
10053
10772
  registerIpc() {
10054
- this.ipc.handle(UpdateChannel.Check, async () => this.check()).handle(UpdateChannel.Download, async () => this.download()).handle(UpdateChannel.Install, async () => this.install());
10773
+ this.ipc.handle(UpdateChannel.Check, async () => this.check()).handle(UpdateChannel.Download, async () => this.download()).handle(UpdateChannel.Install, async () => this.install()).on(UpdateChannel.Close, () => this.hideUpdatePanel());
10055
10774
  }
10056
10775
  async check() {
10057
10776
  try {
@@ -10075,7 +10794,7 @@ var UpdateManager = class {
10075
10794
  }
10076
10795
  try {
10077
10796
  const filePath = await this.checker.downloadUpdate(this.latestUpdate, (percent) => {
10078
- this.mainWindow.webContents.send(UpdateChannel.DownloadProgress, { percent });
10797
+ this.notifyDownloadProgress(percent);
10079
10798
  });
10080
10799
  this.downloadedPath = filePath;
10081
10800
  return { success: true, filePath };
@@ -10103,6 +10822,7 @@ var UpdateManager = class {
10103
10822
  * the timer clears + handler removals are scheduled synchronously.
10104
10823
  */
10105
10824
  dispose() {
10825
+ this.disposed = true;
10106
10826
  if (this.timer) {
10107
10827
  clearInterval(this.timer);
10108
10828
  this.timer = null;
@@ -10119,10 +10839,11 @@ var UpdateManager = class {
10119
10839
  }
10120
10840
  async checkAndNotify() {
10121
10841
  const result = await this.check();
10842
+ if (this.disposed) return;
10122
10843
  if (!result.hasUpdate || !result.info) return;
10123
10844
  if (this.hasNotified) return;
10124
10845
  this.hasNotified = true;
10125
- this.mainWindow.webContents.send(UpdateChannel.Available, result.info);
10846
+ this.showUpdatePanel(result.info);
10126
10847
  }
10127
10848
  };
10128
10849
 
@@ -10471,6 +11192,10 @@ function createContext(config, mainWindow, rendererDir2) {
10471
11192
  projectTemplates: config.projectTemplates,
10472
11193
  builtinTemplates: config.builtinTemplates,
10473
11194
  customCreateProjectDialog: config.customCreateProjectDialog,
11195
+ // No cast needed here: the hook receives the project record, so the
11196
+ // main-process `Project` the context hands it satisfies the structural
11197
+ // `EditableProject` the config declares.
11198
+ customEditProjectDialog: config.customEditProjectDialog,
10474
11199
  onBeforeOpenProject: config.onBeforeOpenProject
10475
11200
  });
10476
11201
  }
@@ -10564,7 +11289,7 @@ function enableDevRendererAutoReload(rendererDir2) {
10564
11289
  const watcher = fs10.watch(rendererDir2, { recursive: true }, () => {
10565
11290
  if (reloadTimer) clearTimeout(reloadTimer);
10566
11291
  reloadTimer = setTimeout(() => {
10567
- for (const win of BrowserWindow6.getAllWindows()) {
11292
+ for (const win of BrowserWindow5.getAllWindows()) {
10568
11293
  win.webContents.reload();
10569
11294
  }
10570
11295
  }, 300);
@@ -10604,6 +11329,8 @@ async function createDevtoolsRuntime(config = {}, onInstanceCreated) {
10604
11329
  context.registry.add(toDisposable5(() => context.internalDevtoolsWindow?.dispose()));
10605
11330
  context.registry.add(registerInternalDevtoolsIpc(context));
10606
11331
  context.registry.add(registerTooltipIpc(context));
11332
+ context.registry.add(registerProjectCreateIpc(context));
11333
+ context.registry.add(registerViewsIpc(context));
10607
11334
  context.registry.add((0, simulator_session_policy_exports.setupSimulatorSessionPolicy)());
10608
11335
  context.registry.add(installThemeBackgroundSync());
10609
11336
  if (!config.adapter) context.registry.add(setupCompileWorkerStandby(context));
@@ -10656,13 +11383,27 @@ async function createDevtoolsRuntime(config = {}, onInstanceCreated) {
10656
11383
  instance.registerSimulatorApi("login", async () => {
10657
11384
  return "hello";
10658
11385
  });
11386
+ context.registry.add(
11387
+ context.views.hostSidebar.onMessage("project-category-selected", (payload) => {
11388
+ const category = payload?.category;
11389
+ if (category !== "miniprogram" && category !== "minigame") return;
11390
+ context.notify.hostSidebarCategorySelected(category);
11391
+ })
11392
+ );
11393
+ context.views.hostSidebar.loadFile(path19.join(rendererDir2, "entries/host-sidebar-default/index.html")).catch((err2) => {
11394
+ console.warn("[workbench] failed to load host-sidebar default content:", err2);
11395
+ });
11396
+ context.views.hostSidebar.setWidthMode({ fixed: HOST_SIDEBAR_DEFAULT_WIDTH });
11397
+ context.views.hostSidebar.setWidthMode("auto");
10659
11398
  if (config.onSetup) {
10660
11399
  await config.onSetup(instance);
10661
11400
  }
10662
11401
  if (config.updateChecker) {
10663
11402
  instance.updateManager = new UpdateManager({
10664
11403
  checker: config.updateChecker,
10665
- mainWindow,
11404
+ showUpdatePanel: (info) => context.views.showUpdateDialog(info),
11405
+ notifyDownloadProgress: (percent) => context.views.notifyUpdateDownloadProgress(percent),
11406
+ hideUpdatePanel: () => context.views.hideUpdateDialog(),
10666
11407
  senderPolicy: context.senderPolicy,
10667
11408
  checkInterval: config.updateOptions?.checkInterval,
10668
11409
  initialDelay: config.updateOptions?.initialDelay,