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

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 (153) hide show
  1. package/dist/main/api.d.ts +1 -1
  2. package/dist/main/app/app.js +55 -2
  3. package/dist/main/index.bundle.js +887 -234
  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 +11 -0
  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/project-repository.d.ts +4 -1
  21. package/dist/main/services/projects/project-repository.js +63 -5
  22. package/dist/main/services/update/update-manager.d.ts +17 -3
  23. package/dist/main/services/update/update-manager.js +25 -6
  24. package/dist/main/services/views/host-dialog-port-channel.d.ts +18 -0
  25. package/dist/main/services/views/host-dialog-port-channel.js +15 -0
  26. package/dist/main/services/views/host-dialog-session-runtime.d.ts +10 -0
  27. package/dist/main/services/views/host-dialog-session-runtime.js +17 -0
  28. package/dist/main/services/views/host-dialog-view.d.ts +95 -0
  29. package/dist/main/services/views/host-dialog-view.js +147 -0
  30. package/dist/main/services/views/host-sidebar-port-channel.d.ts +18 -0
  31. package/dist/main/services/views/host-sidebar-port-channel.js +15 -0
  32. package/dist/main/services/views/host-sidebar-session-runtime.d.ts +10 -0
  33. package/dist/main/services/views/host-sidebar-session-runtime.js +17 -0
  34. package/dist/main/services/views/host-sidebar-view.d.ts +59 -0
  35. package/dist/main/services/views/host-sidebar-view.js +44 -0
  36. package/dist/main/services/views/host-slot-port-channel.d.ts +107 -0
  37. package/dist/main/services/views/host-slot-port-channel.js +261 -0
  38. package/dist/main/services/views/host-slot-session-runtime.d.ts +40 -0
  39. package/dist/main/services/views/host-slot-session-runtime.js +50 -0
  40. package/dist/main/services/views/host-slot-view.d.ts +109 -0
  41. package/dist/main/services/views/host-slot-view.js +147 -0
  42. package/dist/main/services/views/host-toolbar-port-channel.d.ts +6 -91
  43. package/dist/main/services/views/host-toolbar-port-channel.js +10 -243
  44. package/dist/main/services/views/host-toolbar-session-runtime.d.ts +5 -30
  45. package/dist/main/services/views/host-toolbar-session-runtime.js +9 -47
  46. package/dist/main/services/views/host-toolbar-view.d.ts +34 -7
  47. package/dist/main/services/views/host-toolbar-view.js +30 -224
  48. package/dist/main/services/views/managed-web-contents-view.d.ts +48 -0
  49. package/dist/main/services/views/managed-web-contents-view.js +123 -0
  50. package/dist/main/services/views/overlay-panels-view.d.ts +23 -0
  51. package/dist/main/services/views/overlay-panels-view.js +93 -4
  52. package/dist/main/services/views/placement-reconciler.d.ts +14 -2
  53. package/dist/main/services/views/placement-reconciler.js +27 -0
  54. package/dist/main/services/views/placement-test-driver.d.ts +1 -0
  55. package/dist/main/services/views/placement-test-driver.js +3 -0
  56. package/dist/main/services/views/view-manager-devtools-host-test-fixtures.js +3 -1
  57. package/dist/main/services/views/view-manager.d.ts +10 -78
  58. package/dist/main/services/views/view-manager.js +34 -3
  59. package/dist/main/utils/paths.d.ts +4 -0
  60. package/dist/main/utils/paths.js +4 -0
  61. package/dist/main/utils/sender-policy.js +10 -0
  62. package/dist/native-host/common/common.js +65 -62
  63. package/dist/native-host/render/render.js +2230 -2052
  64. package/dist/native-host/service/service.js +2 -2
  65. package/dist/preload/runtime/host-dialog-advertiser.d.ts +22 -0
  66. package/dist/preload/runtime/host-dialog-advertiser.js +37 -0
  67. package/dist/preload/runtime/host-dialog-port.d.ts +44 -0
  68. package/dist/preload/runtime/host-dialog-port.js +53 -0
  69. package/dist/preload/runtime/host-dialog-runtime.d.ts +28 -0
  70. package/dist/preload/runtime/host-dialog-runtime.js +36 -0
  71. package/dist/preload/runtime/host-sidebar-advertiser.d.ts +19 -0
  72. package/dist/preload/runtime/host-sidebar-advertiser.js +35 -0
  73. package/dist/preload/runtime/host-sidebar-port.d.ts +44 -0
  74. package/dist/preload/runtime/host-sidebar-port.js +53 -0
  75. package/dist/preload/runtime/host-sidebar-runtime.d.ts +28 -0
  76. package/dist/preload/runtime/host-sidebar-runtime.js +36 -0
  77. package/dist/preload/runtime/host-slot-port-bridge.d.ts +18 -0
  78. package/dist/preload/runtime/host-slot-port-bridge.js +112 -0
  79. package/dist/preload/runtime/host-toolbar-advertiser.d.ts +5 -13
  80. package/dist/preload/runtime/host-toolbar-advertiser.js +18 -38
  81. package/dist/preload/runtime/host-toolbar-port.d.ts +9 -0
  82. package/dist/preload/runtime/host-toolbar-port.js +11 -95
  83. package/dist/preload/runtime/wait-for-slot-root.d.ts +20 -0
  84. package/dist/preload/runtime/wait-for-slot-root.js +52 -0
  85. package/dist/preload/windows/host-dialog-runtime.cjs +353 -0
  86. package/dist/preload/windows/host-dialog-runtime.cjs.map +7 -0
  87. package/dist/preload/windows/host-dialog-runtime.d.ts +2 -0
  88. package/dist/preload/windows/host-dialog-runtime.js +13 -0
  89. package/dist/preload/windows/host-sidebar-runtime.cjs +354 -0
  90. package/dist/preload/windows/host-sidebar-runtime.cjs.map +7 -0
  91. package/dist/preload/windows/host-sidebar-runtime.d.ts +2 -0
  92. package/dist/preload/windows/host-sidebar-runtime.js +13 -0
  93. package/dist/preload/windows/host-toolbar-runtime.cjs +134 -51
  94. package/dist/preload/windows/host-toolbar-runtime.cjs.map +3 -3
  95. package/dist/preload/windows/simulator.cjs.map +1 -1
  96. package/dist/renderer/assets/button-DsNqZm7o.js +2 -0
  97. package/dist/renderer/assets/constants-D7DfVqMp.js +2 -0
  98. package/dist/renderer/assets/constants-D8zsejFq.js +2 -0
  99. package/dist/renderer/assets/createLucideIcon-CYJeT1ji.js +2 -0
  100. package/dist/renderer/assets/dialog-pT4qWmka.js +46 -0
  101. package/dist/renderer/assets/dist-o70xmpc1.js +2 -0
  102. package/dist/renderer/assets/hostSidebarDefault-NvGZlE9O.js +2 -0
  103. package/dist/renderer/assets/index-zErhG3ta.js +5 -0
  104. package/dist/renderer/assets/input-4QxTXMZN.js +2 -0
  105. package/dist/renderer/assets/ipc-channels-overlays-Blr5TNoB.js +2 -0
  106. package/dist/renderer/assets/jsx-runtime-B-3rq1y5.css +1 -0
  107. package/dist/renderer/assets/jsx-runtime-CqVdW3eg.js +9 -0
  108. package/dist/renderer/assets/popover-CJiSWwuE.js +2 -0
  109. package/dist/renderer/assets/project-api-DZ1Zi6EC.js +2 -0
  110. package/dist/renderer/assets/projectCreateDialog-DMWNhw_1.js +2 -0
  111. package/dist/renderer/assets/select-C86pNcsu.js +2 -0
  112. package/dist/renderer/assets/settings-BoI8mLT1.js +2 -0
  113. package/dist/renderer/assets/settings-api-Bs_g4NHs.js +2 -0
  114. package/dist/renderer/assets/settings-tab-bar-DHLLygqv.js +2 -0
  115. package/dist/renderer/assets/tooltip-BhAyY0T4.js +2 -0
  116. package/dist/renderer/assets/types-YYjkvane.js +2 -0
  117. package/dist/renderer/assets/updateDialog-DPum3wx1.js +2 -0
  118. package/dist/renderer/assets/utils-kfQov6Pa.js +2 -0
  119. package/dist/renderer/assets/view-api-DFhb2R8-.js +2 -0
  120. package/dist/renderer/assets/{workbenchSettings-oq_EyfKf.js → workbenchSettings-DrajRQUk.js} +3 -3
  121. package/dist/renderer/entries/host-sidebar-default/index.html +21 -0
  122. package/dist/renderer/entries/main/index.html +15 -8
  123. package/dist/renderer/entries/popover/index.html +10 -7
  124. package/dist/renderer/entries/project-create-dialog/index.html +27 -0
  125. package/dist/renderer/entries/settings/index.html +10 -7
  126. package/dist/renderer/entries/tooltip/index.html +5 -4
  127. package/dist/renderer/entries/update-dialog/index.html +25 -0
  128. package/dist/renderer/entries/workbench-settings/index.html +11 -7
  129. package/dist/service-host/preload.cjs +10 -0
  130. package/dist/shared/constants.d.ts +22 -0
  131. package/dist/shared/constants.js +22 -0
  132. package/dist/shared/ipc-channels-overlays.d.ts +156 -0
  133. package/dist/shared/ipc-channels-overlays.js +186 -0
  134. package/dist/shared/ipc-channels.d.ts +0 -77
  135. package/dist/shared/ipc-channels.js +0 -98
  136. package/dist/shared/ipc-schemas.d.ts +33 -0
  137. package/dist/shared/ipc-schemas.js +41 -0
  138. package/dist/shared/types.d.ts +10 -0
  139. package/dist/shared/view-ids.d.ts +7 -0
  140. package/dist/shared/view-ids.js +10 -0
  141. package/package.json +8 -8
  142. package/dist/renderer/assets/constants-Bdz0LHdy.js +0 -2
  143. package/dist/renderer/assets/index-CtznrmHR.js +0 -49
  144. package/dist/renderer/assets/input-Dmm6nob5.js +0 -2
  145. package/dist/renderer/assets/ipc-transport-BOg0gR9W.js +0 -9
  146. package/dist/renderer/assets/ipc-transport-DgQhZaE9.css +0 -1
  147. package/dist/renderer/assets/popover-Cd1FEGOX.js +0 -2
  148. package/dist/renderer/assets/select-BaYox7If.js +0 -2
  149. package/dist/renderer/assets/settings-BXvwuFaz.js +0 -2
  150. package/dist/renderer/assets/settings-api-Bo9GbYqs.js +0 -2
  151. package/dist/renderer/assets/settings-tab-bar-Beia6lMr.js +0 -2
  152. package/dist/renderer/assets/tooltip-DfQqK3Sk.js +0 -2
  153. 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";
@@ -494,64 +497,6 @@ var ProjectsChannel = {
494
497
  var DialogChannel = {
495
498
  OpenDirectory: "dialog:openDirectory"
496
499
  };
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
500
  var WindowChannel = {
556
501
  NavigateBack: "window:navigateBack",
557
502
  OpenProject: "window:openProject",
@@ -574,19 +519,6 @@ var InternalDevtoolsChannel = {
574
519
  // its own dedicated window (see internal-devtools-window/index.ts).
575
520
  Open: "internal-devtools:open"
576
521
  };
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
522
 
591
523
  // src/main/ipc/project-fs.ts
592
524
  import { WATCH_IGNORE_DIRS } from "@dimina-kit/devkit/watch-ignore";
@@ -921,7 +853,7 @@ function registerProjectFsIpc(ctx) {
921
853
  }
922
854
 
923
855
  // src/main/app/app.ts
924
- import { app as app13, BrowserWindow as BrowserWindow6, nativeImage, session as session2 } from "electron";
856
+ import { app as app13, BrowserWindow as BrowserWindow5, nativeImage, session as session2 } from "electron";
925
857
  import fs10 from "fs";
926
858
  import path19 from "path";
927
859
 
@@ -954,6 +886,14 @@ var hostToolbarRuntimePreloadPath = path3.join(
954
886
  devtoolsPackageRoot,
955
887
  "dist/preload/windows/host-toolbar-runtime.cjs"
956
888
  );
889
+ var hostSidebarRuntimePreloadPath = path3.join(
890
+ devtoolsPackageRoot,
891
+ "dist/preload/windows/host-sidebar-runtime.cjs"
892
+ );
893
+ var hostDialogRuntimePreloadPath = path3.join(
894
+ devtoolsPackageRoot,
895
+ "dist/preload/windows/host-dialog-runtime.cjs"
896
+ );
957
897
  var simulatorDir = path3.join(devtoolsPackageRoot, "dist/simulator");
958
898
  var runtimeAssetPaths = {
959
899
  root: path3.join(devtoolsPackageRoot, "dist"),
@@ -1595,6 +1535,10 @@ function createWorkbenchSenderPolicy(ctx) {
1595
1535
  if (popoverViewId != null && sender.id === popoverViewId) return true;
1596
1536
  const tooltipViewId = ctx.views.getTooltipWebContentsId();
1597
1537
  if (tooltipViewId != null && sender.id === tooltipViewId) return true;
1538
+ const projectCreateDialogViewId = ctx.views.getProjectCreateDialogWebContentsId();
1539
+ if (projectCreateDialogViewId != null && sender.id === projectCreateDialogViewId) return true;
1540
+ const updateDialogViewId = ctx.views.getUpdateDialogWebContentsId();
1541
+ if (updateDialogViewId != null && sender.id === updateDialogViewId) return true;
1598
1542
  return false;
1599
1543
  };
1600
1544
  }
@@ -1614,6 +1558,148 @@ var defaultAdapter = {
1614
1558
  }
1615
1559
  };
1616
1560
 
1561
+ // src/shared/ipc-channels-overlays.ts
1562
+ var ViewChannel = {
1563
+ /**
1564
+ * Reverse size-advertiser: the host-toolbar WCV's OWN renderer advertises its
1565
+ * intrinsic content height so main reserves exactly that much. Payload
1566
+ * `{ axis: 'block', extent }`. fire-and-forget (send), NOT invoke.
1567
+ */
1568
+ HostToolbarAdvertiseHeight: "view:host-toolbar:advertise-height",
1569
+ /**
1570
+ * main → host-toolbar WCV renderer: per-load MessagePort handshake for the
1571
+ * gated narrow channel. On every toolbar `did-finish-load` main creates a
1572
+ * `MessageChannelMain` and transfers port2 here
1573
+ * (`wc.postMessage(HostToolbarPort, null, [port2])`); the session-resident
1574
+ * toolbar runtime preload receives it via `event.ports[0]` and bridges it to
1575
+ * the page as `window.diminaHostToolbar`. Envelope both directions:
1576
+ * `{ channel: string, payload: unknown }`.
1577
+ */
1578
+ HostToolbarPort: "view:host-toolbar:port",
1579
+ /**
1580
+ * main → main-window renderer: push the reserved host-toolbar height so the
1581
+ * renderer placeholder div resizes (closing the dynamic-height loop).
1582
+ */
1583
+ HostToolbarHeightChanged: "view:host-toolbar:height-changed",
1584
+ /**
1585
+ * main ← main-window renderer (invoke): pull the last NOTIFIED toolbar
1586
+ * height retained in main. Mount-time replay companion to
1587
+ * `HostToolbarHeightChanged`: the push listener mounts with the project
1588
+ * view and the toolbar's size-advertiser deduplicates (never re-reports),
1589
+ * so a height pushed while no project view was mounted would otherwise be
1590
+ * lost forever (cold start on the project list races it; close-project →
1591
+ * reopen hits it deterministically). No payload; resolves a number.
1592
+ */
1593
+ HostToolbarGetHeight: "view:host-toolbar:get-height",
1594
+ /**
1595
+ * Reverse size-advertiser for the host-sidebar WCV, mirroring
1596
+ * `HostToolbarAdvertiseHeight` on the inline (width) axis instead of block.
1597
+ * Payload `{ axis: 'inline', extent }`. fire-and-forget (send), NOT invoke.
1598
+ */
1599
+ HostSidebarAdvertiseWidth: "view:host-sidebar:advertise-width",
1600
+ /**
1601
+ * main → host-sidebar WCV renderer: per-load MessagePort handshake, same
1602
+ * contract as `HostToolbarPort` (see that entry).
1603
+ */
1604
+ HostSidebarPort: "view:host-sidebar:port",
1605
+ /**
1606
+ * main → main-window renderer: push the reserved host-sidebar width so the
1607
+ * renderer placeholder div resizes, mirroring `HostToolbarHeightChanged`.
1608
+ */
1609
+ HostSidebarWidthChanged: "view:host-sidebar:width-changed",
1610
+ /**
1611
+ * main ← main-window renderer (invoke): pull the last NOTIFIED sidebar
1612
+ * width, mirroring `HostToolbarGetHeight`'s mount-time replay role.
1613
+ */
1614
+ HostSidebarGetWidth: "view:host-sidebar:get-width",
1615
+ /**
1616
+ * main → main-window renderer: push the project category (`Project.type`)
1617
+ * selected in the host-sidebar's content — devtools' own default icon rail,
1618
+ * or any downstream replacement that sends on the same channel. No
1619
+ * pull/replay companion like `HostSidebarGetWidth`: the default category is
1620
+ * a stable initial value regardless of load-order, and nothing is ever sent
1621
+ * before the main-window renderer (and thus `ProjectListScreen`) is already
1622
+ * mounted.
1623
+ */
1624
+ HostSidebarCategorySelected: "view:host-sidebar:category-selected",
1625
+ /**
1626
+ * Reverse size-advertiser for the host-dialog WCV. Unlike the toolbar/sidebar
1627
+ * (single-axis, `setBaseDesired`-placed strips), the dialog is a BOTH-AXES
1628
+ * overlay positioned by `setOverlayDesired` — main centers it in the main
1629
+ * window once it knows both dimensions. One channel carries either axis'
1630
+ * report (`{ axis: 'block' | 'inline', extent }`); the dialog's own content
1631
+ * advertises both from the same root (see `host-dialog-advertiser.ts`).
1632
+ * fire-and-forget (send), NOT invoke.
1633
+ *
1634
+ * No `HostDialogSizeChanged` / `HostDialogGetSize` counterparts: those exist
1635
+ * for toolbar/sidebar so a renderer-owned PLACEHOLDER can replay a size it
1636
+ * missed. The dialog has no such placeholder — it is a main-driven overlay
1637
+ * shown/hidden on demand (`hostDialog.show()`/`hide()`), so there is nothing
1638
+ * in the renderer to replay a size into.
1639
+ */
1640
+ HostDialogAdvertiseSize: "view:host-dialog:advertise-size",
1641
+ /**
1642
+ * main → host-dialog WCV renderer: per-load MessagePort handshake, same
1643
+ * contract as `HostToolbarPort` (see that entry).
1644
+ */
1645
+ HostDialogPort: "view:host-dialog:port",
1646
+ /**
1647
+ * Renderer → main: the window-level placement snapshot (one monotonic epoch
1648
+ * per commit tick, one generation per renderer lifetime) that drives the view
1649
+ * reconciler. The single source of truth for every managed native view's
1650
+ * bounds/visibility/z-order — supersedes the per-view bounds channels above.
1651
+ * invoke.
1652
+ */
1653
+ PlacementSnapshot: "view:placement-snapshot",
1654
+ /**
1655
+ * main ← main-window renderer (invoke): allocate a fresh placement
1656
+ * generation seed for this renderer bootstrap. See
1657
+ * renderer-placement-generation.ts for why the seed comes from main
1658
+ * (a wall-clock `Date.now()` seed is not guaranteed to exceed main's
1659
+ * still-standing high-water mark across two reloads that happen faster
1660
+ * than the clock's resolution). No payload; resolves a number.
1661
+ */
1662
+ AllocatePlacementGeneration: "view:allocate-placement-generation"
1663
+ };
1664
+ var PopoverChannel = {
1665
+ Show: "popover:show",
1666
+ Hide: "popover:hide",
1667
+ Relaunch: "popover:relaunch",
1668
+ Closed: "popover:closed",
1669
+ Init: "popover:init"
1670
+ };
1671
+ var OverlayChannel = {
1672
+ Ready: "overlay:ready"
1673
+ };
1674
+ var TooltipChannel = {
1675
+ Prepare: "tooltip:prepare",
1676
+ Show: "tooltip:show",
1677
+ Hide: "tooltip:hide",
1678
+ Init: "tooltip:init",
1679
+ Measured: "tooltip:measured"
1680
+ };
1681
+ var ProjectCreateChannel = {
1682
+ Show: "projectCreate:show",
1683
+ Init: "projectCreate:init",
1684
+ Submit: "projectCreate:submit",
1685
+ Cancel: "projectCreate:cancel",
1686
+ Submitted: "projectCreate:submitted"
1687
+ };
1688
+ var SettingsChannel = {
1689
+ SetVisible: "settings:setVisible",
1690
+ ConfigChanged: "settings:configChanged",
1691
+ ProjectSettingsChanged: "settings:projectSettingsChanged",
1692
+ Init: "settings:init"
1693
+ };
1694
+ var UpdateChannel = {
1695
+ Check: "updates:check",
1696
+ Download: "updates:download",
1697
+ Install: "updates:install",
1698
+ DownloadProgress: "updates:downloadProgress",
1699
+ Available: "updates:available",
1700
+ Close: "updates:close"
1701
+ };
1702
+
1617
1703
  // src/main/services/notifications/renderer-notifier.ts
1618
1704
  function liveWebContents(wc) {
1619
1705
  if (!wc) return null;
@@ -1652,9 +1738,18 @@ function createRendererNotifier(ctx) {
1652
1738
  hostToolbarHeightChanged(height) {
1653
1739
  sendToMain(ViewChannel.HostToolbarHeightChanged, height);
1654
1740
  },
1741
+ hostSidebarWidthChanged(width) {
1742
+ sendToMain(ViewChannel.HostSidebarWidthChanged, width);
1743
+ },
1744
+ hostSidebarCategorySelected(category) {
1745
+ sendToMain(ViewChannel.HostSidebarCategorySelected, category);
1746
+ },
1655
1747
  editorOpenFile(payload) {
1656
1748
  sendToMain(EditorChannel.OpenFile, payload);
1657
1749
  },
1750
+ projectCreateSubmitted(payload) {
1751
+ sendToMain(ProjectCreateChannel.Submitted, payload);
1752
+ },
1658
1753
  popoverInit(popoverView, payload) {
1659
1754
  const wc = liveWebContents(popoverView.webContents);
1660
1755
  if (!wc) return;
@@ -1665,6 +1760,16 @@ function createRendererNotifier(ctx) {
1665
1760
  if (!wc) return;
1666
1761
  wc.send(TooltipChannel.Init, payload);
1667
1762
  },
1763
+ projectCreateInit(dialogView, payload) {
1764
+ const wc = liveWebContents(dialogView.webContents);
1765
+ if (!wc) return;
1766
+ wc.send(ProjectCreateChannel.Init, payload);
1767
+ },
1768
+ updateAvailable(dialogView, payload) {
1769
+ const wc = liveWebContents(dialogView.webContents);
1770
+ if (!wc) return;
1771
+ wc.send(UpdateChannel.Available, payload);
1772
+ },
1668
1773
  settingsInit(payload) {
1669
1774
  const wc = liveWebContents(ctx.views.getSettingsWebContents());
1670
1775
  if (!wc) return;
@@ -1933,6 +2038,7 @@ function createPlacementReconciler(ctx) {
1933
2038
  let placementState = createInitialState();
1934
2039
  let epochCounter = 0;
1935
2040
  let rendererGeneration = 0;
2041
+ let allocatedGeneration = 0;
1936
2042
  const appliedActual = /* @__PURE__ */ new Map();
1937
2043
  const baseDesired = /* @__PURE__ */ new Map();
1938
2044
  const overlayDesired = /* @__PURE__ */ new Map();
@@ -2022,6 +2128,12 @@ function createPlacementReconciler(ctx) {
2022
2128
  placementState = { ...placementState, actual: cloneAppliedActual() };
2023
2129
  }
2024
2130
  function setPlacementSnapshot(snapshot) {
2131
+ if (snapshot.generation < rendererGeneration) {
2132
+ console.warn(
2133
+ `[placement-reconciler] snapshot generation ${snapshot.generation} is behind the current ${rendererGeneration}; dropping without applying its content`
2134
+ );
2135
+ return;
2136
+ }
2025
2137
  rendererGeneration = snapshot.generation;
2026
2138
  baseDesired.clear();
2027
2139
  for (const v of snapshot.views) baseDesired.set(v.viewId, v);
@@ -2059,7 +2171,11 @@ function createPlacementReconciler(ctx) {
2059
2171
  deleteOverlayDesired: (viewId) => {
2060
2172
  overlayDesired.delete(viewId);
2061
2173
  },
2062
- hasOverlayDesired: (viewId) => overlayDesired.has(viewId)
2174
+ hasOverlayDesired: (viewId) => overlayDesired.has(viewId),
2175
+ allocateGeneration: () => {
2176
+ allocatedGeneration = Math.max(allocatedGeneration, rendererGeneration) + 1;
2177
+ return allocatedGeneration;
2178
+ }
2063
2179
  };
2064
2180
  }
2065
2181
 
@@ -2072,16 +2188,26 @@ var VIEW_ID = {
2072
2188
  simulatorDevtools: "simulator-devtools",
2073
2189
  workbench: "workbench",
2074
2190
  hostToolbar: "host-toolbar",
2191
+ hostSidebar: "host-sidebar",
2192
+ hostDialog: "host-dialog",
2075
2193
  settings: "settings",
2076
2194
  popover: "popover",
2077
- tooltip: "tooltip"
2195
+ tooltip: "tooltip",
2196
+ projectCreateDialog: "project-create-dialog",
2197
+ updateDialog: "update-dialog"
2078
2198
  };
2079
2199
  var VIEW_LAYER = {
2080
2200
  base: 0,
2081
2201
  hostToolbar: 5,
2202
+ hostSidebar: 5,
2082
2203
  settings: 10,
2083
2204
  popover: 20,
2084
- tooltip: 30
2205
+ tooltip: 30,
2206
+ // devtools' own ProjectCreateDialog/UpdateDialog panels (createOverlayPanel).
2207
+ dialog: 40,
2208
+ // Host-controlled fully-custom dialog (loadURL-level takeover); sits above
2209
+ // devtools' own dialog layer so host content is never occluded by it.
2210
+ hostDialog: 45
2085
2211
  };
2086
2212
 
2087
2213
  // src/main/services/views/workbench-view.ts
@@ -4855,34 +4981,44 @@ function createDevtoolsHost(ctx, reconciler, deps) {
4855
4981
  };
4856
4982
  }
4857
4983
 
4858
- // src/main/services/views/host-toolbar-view.ts
4859
- import { WebContentsView as WebContentsView5 } from "electron";
4984
+ // src/main/services/views/host-slot-session-runtime.ts
4985
+ import { session } from "electron";
4986
+ function createHostSlotSessionRuntime(preloadPath) {
4987
+ let refCount = 0;
4988
+ let registrationId = null;
4989
+ return {
4990
+ acquire() {
4991
+ if (refCount === 0) {
4992
+ registrationId = session.defaultSession.registerPreloadScript({
4993
+ type: "frame",
4994
+ filePath: preloadPath
4995
+ });
4996
+ }
4997
+ refCount++;
4998
+ },
4999
+ release() {
5000
+ if (refCount === 0) return;
5001
+ refCount--;
5002
+ if (refCount === 0 && registrationId !== null) {
5003
+ session.defaultSession.unregisterPreloadScript(registrationId);
5004
+ registrationId = null;
5005
+ }
5006
+ }
5007
+ };
5008
+ }
4860
5009
 
4861
5010
  // src/main/services/views/host-toolbar-session-runtime.ts
4862
- import { session } from "electron";
4863
- var refCount = 0;
4864
- var registrationId = null;
5011
+ var runtime = createHostSlotSessionRuntime(hostToolbarRuntimePreloadPath);
4865
5012
  function acquireHostToolbarSessionRuntime() {
4866
- if (refCount === 0) {
4867
- registrationId = session.defaultSession.registerPreloadScript({
4868
- type: "frame",
4869
- filePath: hostToolbarRuntimePreloadPath
4870
- });
4871
- }
4872
- refCount++;
5013
+ runtime.acquire();
4873
5014
  }
4874
5015
  function releaseHostToolbarSessionRuntime() {
4875
- if (refCount === 0) return;
4876
- refCount--;
4877
- if (refCount === 0 && registrationId !== null) {
4878
- session.defaultSession.unregisterPreloadScript(registrationId);
4879
- registrationId = null;
4880
- }
5016
+ runtime.release();
4881
5017
  }
4882
5018
 
4883
- // src/main/services/views/host-toolbar-port-channel.ts
5019
+ // src/main/services/views/host-slot-port-channel.ts
4884
5020
  import { MessageChannelMain } from "electron";
4885
- function createHostToolbarPortChannel(opts) {
5021
+ function createHostSlotPortChannel(opts) {
4886
5022
  let activePort = null;
4887
5023
  let activeWc = null;
4888
5024
  let state = "absent";
@@ -4894,7 +5030,14 @@ function createHostToolbarPortChannel(opts) {
4894
5030
  const { channel, payload } = data;
4895
5031
  if (typeof channel !== "string") return;
4896
5032
  for (const entry of [...handlers2]) {
4897
- if (entry.channel === channel) entry.handler(payload);
5033
+ if (entry.channel === channel) invokeMessageHandler(entry.handler, payload);
5034
+ }
5035
+ }
5036
+ function invokeMessageHandler(handler, payload) {
5037
+ try {
5038
+ handler(payload);
5039
+ } catch (err2) {
5040
+ console.error(`${opts.logPrefix} onMessage handler threw:`, err2);
4898
5041
  }
4899
5042
  }
4900
5043
  function dropActivePort(close, next) {
@@ -4913,7 +5056,7 @@ function createHostToolbarPortChannel(opts) {
4913
5056
  try {
4914
5057
  handler();
4915
5058
  } catch (err2) {
4916
- console.error("[host-toolbar] onReady handler threw:", err2);
5059
+ console.error(`${opts.logPrefix} onReady handler threw:`, err2);
4917
5060
  }
4918
5061
  }
4919
5062
  function fireReadyHandlers() {
@@ -4932,7 +5075,7 @@ function createHostToolbarPortChannel(opts) {
4932
5075
  port1.on("close", () => {
4933
5076
  if (activePort === port1) dropActivePort(false, "absent");
4934
5077
  });
4935
- wc.postMessage(ViewChannel.HostToolbarPort, null, [port2]);
5078
+ wc.postMessage(opts.channel, null, [port2]);
4936
5079
  port1.start();
4937
5080
  activePort = port1;
4938
5081
  activeWc = wc;
@@ -4963,7 +5106,7 @@ function createHostToolbarPortChannel(opts) {
4963
5106
  onMessage(channel, handler) {
4964
5107
  if (typeof channel !== "string" || channel === "") {
4965
5108
  throw new TypeError(
4966
- "hostToolbar.onMessage: channel must be a non-empty string"
5109
+ `${opts.logPrefix} onMessage: channel must be a non-empty string`
4967
5110
  );
4968
5111
  }
4969
5112
  const entry = { channel, handler };
@@ -5011,135 +5154,401 @@ function createHostToolbarPortChannel(opts) {
5011
5154
  };
5012
5155
  }
5013
5156
 
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
5157
+ // src/main/services/views/host-toolbar-port-channel.ts
5158
+ function createHostToolbarPortChannel(opts) {
5159
+ return createHostSlotPortChannel({
5160
+ isCurrent: opts.isCurrent,
5161
+ channel: ViewChannel.HostToolbarPort,
5162
+ logPrefix: "[host-toolbar]"
5023
5163
  });
5024
- function liveHostToolbarWebContents() {
5025
- const wc = hostToolbarView?.webContents;
5164
+ }
5165
+
5166
+ // src/main/services/views/managed-web-contents-view.ts
5167
+ import { WebContentsView as WebContentsView5 } from "electron";
5168
+ function createManagedWebContentsView(opts) {
5169
+ let view = null;
5170
+ let preloadOverride = null;
5171
+ let runtimeAcquired = false;
5172
+ function liveWebContents2() {
5173
+ const wc = view?.webContents;
5026
5174
  if (!wc || wc.isDestroyed()) return null;
5027
5175
  return wc;
5028
5176
  }
5029
- function ensureHostToolbarView() {
5030
- if (hostToolbarView && liveHostToolbarWebContents()) {
5031
- return hostToolbarView;
5177
+ function teardown(current, detail) {
5178
+ if (view !== current) return;
5179
+ console.error(`[${opts.viewId}] ${detail} \u2014 destroying so the next ensureView() rebuilds`);
5180
+ view = null;
5181
+ opts.reconciler.destroyView(opts.viewId, current);
5182
+ opts.onBroken?.();
5183
+ }
5184
+ function ensureView() {
5185
+ if (view && liveWebContents2()) {
5186
+ return view;
5032
5187
  }
5033
- if (hostToolbarView) {
5034
- reconciler.destroyView(VIEW_ID.hostToolbar, hostToolbarView);
5188
+ if (view) {
5189
+ opts.reconciler.destroyView(opts.viewId, view);
5035
5190
  }
5036
- if (!hostToolbarRuntimeAcquired) {
5037
- acquireHostToolbarSessionRuntime();
5038
- hostToolbarRuntimeAcquired = true;
5191
+ if (!runtimeAcquired) {
5192
+ opts.sessionRuntime.acquire();
5193
+ runtimeAcquired = true;
5039
5194
  }
5040
5195
  const webPreferences = {
5041
5196
  nodeIntegration: false,
5042
5197
  contextIsolation: true,
5043
5198
  sandbox: false,
5044
- additionalArguments: [HOST_TOOLBAR_RUNTIME_MARKER]
5199
+ additionalArguments: [opts.marker]
5045
5200
  };
5046
- if (hostToolbarPreloadOverride !== null) {
5047
- webPreferences.preload = hostToolbarPreloadOverride;
5201
+ if (preloadOverride !== null) {
5202
+ webPreferences.preload = preloadOverride;
5048
5203
  }
5049
- const view = new WebContentsView5({ webPreferences });
5050
- hostToolbarView = view;
5051
- hostToolbarPort.attach(view.webContents);
5204
+ const next = new WebContentsView5({ webPreferences });
5205
+ view = next;
5206
+ opts.port.attach(next.webContents);
5052
5207
  try {
5053
- view.setBackgroundColor("#121212");
5208
+ next.setBackgroundColor("#121212");
5054
5209
  } catch {
5055
5210
  }
5056
5211
  try {
5057
- view.webContents.setWindowOpenHandler(({ url }) => handleWindowOpenExternal(url));
5212
+ next.webContents.setWindowOpenHandler(({ url }) => handleWindowOpenExternal(url));
5058
5213
  } catch {
5059
5214
  }
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
5215
+ next.webContents.on("did-fail-load", (_event, errorCode, _errorDescription, _validatedURL, isMainFrame) => {
5216
+ if (!isMainFrame || errorCode === -3) return;
5217
+ teardown(next, `did-fail-load (code ${errorCode})`);
5076
5218
  });
5077
- reconciler.reconcileNow();
5078
- notifyHostToolbarHeight(0);
5219
+ next.webContents.on("render-process-gone", (_event, details) => {
5220
+ teardown(next, `render-process-gone (${details.reason})`);
5221
+ });
5222
+ return next;
5079
5223
  }
5080
- const control = {
5224
+ return {
5081
5225
  async loadURL(url) {
5082
- const view = ensureHostToolbarView();
5083
- hostToolbarPort.invalidate();
5084
- await view.webContents.loadURL(url);
5226
+ const v = ensureView();
5227
+ opts.port.invalidate();
5228
+ await v.webContents.loadURL(url);
5085
5229
  },
5086
5230
  async loadFile(filePath) {
5087
- const view = ensureHostToolbarView();
5088
- hostToolbarPort.invalidate();
5089
- await view.webContents.loadFile(filePath);
5231
+ const v = ensureView();
5232
+ opts.port.invalidate();
5233
+ await v.webContents.loadFile(filePath);
5234
+ },
5235
+ liveWebContents: liveWebContents2,
5236
+ getView: () => view,
5237
+ setPreloadPath(path20) {
5238
+ preloadOverride = path20;
5090
5239
  },
5240
+ ensureView,
5241
+ dispose() {
5242
+ opts.port.dispose();
5243
+ opts.reconciler.destroyView(opts.viewId, view);
5244
+ view = null;
5245
+ if (runtimeAcquired) {
5246
+ opts.sessionRuntime.release();
5247
+ runtimeAcquired = false;
5248
+ }
5249
+ }
5250
+ };
5251
+ }
5252
+
5253
+ // src/main/services/views/host-slot-view.ts
5254
+ function deriveSlotControl(base, extra) {
5255
+ return {
5256
+ loadURL: (url) => base.loadURL(url),
5257
+ loadFile: (filePath) => base.loadFile(filePath),
5091
5258
  get webContents() {
5092
- return liveHostToolbarWebContents();
5259
+ return base.webContents;
5093
5260
  },
5094
- hide() {
5095
- hideHostToolbar();
5261
+ hide: () => base.hide(),
5262
+ setPreloadPath: (path20) => base.setPreloadPath(path20),
5263
+ onMessage: (channel, handler) => base.onMessage(channel, handler),
5264
+ onReady: (handler) => base.onReady(handler),
5265
+ send: (channel, payload) => base.send(channel, payload),
5266
+ ...extra
5267
+ };
5268
+ }
5269
+ function createHostSlotView(reconciler, config, deps) {
5270
+ let extentMode = "auto";
5271
+ let lastExtent = 0;
5272
+ let lastAdvertisedExtent = null;
5273
+ const port = config.portChannel;
5274
+ const managed = createManagedWebContentsView({
5275
+ reconciler,
5276
+ viewId: config.viewId,
5277
+ marker: config.marker,
5278
+ sessionRuntime: config.sessionRuntime,
5279
+ port
5280
+ });
5281
+ function notifyExtent(extent) {
5282
+ lastExtent = extent;
5283
+ deps.onExtentChanged(extent);
5284
+ deps.reapplyPresentOverlays?.();
5285
+ }
5286
+ function setExtent(extent) {
5287
+ lastAdvertisedExtent = extent;
5288
+ if (extentMode !== "auto") return;
5289
+ notifyExtent(extent);
5290
+ }
5291
+ function hideView() {
5292
+ reconciler.setBaseDesired(config.viewId, {
5293
+ viewId: config.viewId,
5294
+ placement: { visible: false },
5295
+ layer: config.layer
5296
+ });
5297
+ reconciler.reconcileNow();
5298
+ notifyExtent(0);
5299
+ lastAdvertisedExtent = null;
5300
+ }
5301
+ const control = {
5302
+ loadURL: (url) => managed.loadURL(url),
5303
+ loadFile: (filePath) => managed.loadFile(filePath),
5304
+ get webContents() {
5305
+ return managed.liveWebContents();
5096
5306
  },
5097
- setPreloadPath(path20) {
5098
- hostToolbarPreloadOverride = path20;
5307
+ hide() {
5308
+ hideView();
5099
5309
  },
5100
- setHeightMode(mode) {
5310
+ setPreloadPath: (path20) => managed.setPreloadPath(path20),
5311
+ setExtentMode(mode) {
5101
5312
  if (mode !== "auto" && !(Number.isFinite(mode.fixed) && mode.fixed >= 0)) {
5102
5313
  throw new TypeError(
5103
- `hostToolbar.setHeightMode: fixed height must be a finite, non-negative number (got ${mode.fixed})`
5314
+ `${config.setExtentModeErrorLabel}: fixed extent must be a finite, non-negative number (got ${mode.fixed})`
5104
5315
  );
5105
5316
  }
5106
- hostToolbarHeightMode = mode;
5317
+ extentMode = mode;
5107
5318
  if (mode !== "auto") {
5108
- notifyHostToolbarHeight(mode.fixed);
5319
+ notifyExtent(mode.fixed);
5320
+ } else if (lastAdvertisedExtent !== null && lastAdvertisedExtent !== lastExtent) {
5321
+ notifyExtent(lastAdvertisedExtent);
5109
5322
  }
5110
5323
  },
5111
5324
  onMessage(channel, handler) {
5112
- return hostToolbarPort.onMessage(channel, handler);
5325
+ return port.onMessage(channel, handler);
5113
5326
  },
5114
5327
  onReady(handler) {
5115
- return hostToolbarPort.onReady(handler);
5328
+ return port.onReady(handler);
5116
5329
  },
5117
5330
  send(channel, payload) {
5118
- return hostToolbarPort.send(channel, payload);
5331
+ return port.send(channel, payload);
5119
5332
  }
5120
5333
  };
5121
- reconciler.registerView(VIEW_ID.hostToolbar, {
5122
- getView: () => hostToolbarView,
5123
- ensureView: () => ensureHostToolbarView(),
5334
+ reconciler.registerView(config.viewId, {
5335
+ getView: () => managed.getView(),
5336
+ ensureView: () => managed.ensureView(),
5124
5337
  ensureLazy: (desired) => {
5125
- if (desired?.placement.visible && !liveHostToolbarWebContents()) ensureHostToolbarView();
5338
+ if (desired?.placement.visible && !managed.liveWebContents()) managed.ensureView();
5339
+ }
5340
+ });
5341
+ return {
5342
+ control,
5343
+ setExtent,
5344
+ getExtent: () => lastExtent,
5345
+ getWebContentsId: () => managed.liveWebContents()?.id ?? null,
5346
+ dispose: () => managed.dispose()
5347
+ };
5348
+ }
5349
+
5350
+ // src/main/services/views/host-toolbar-view.ts
5351
+ function createHostToolbarView(ctx, reconciler, deps) {
5352
+ const port = createHostToolbarPortChannel({
5353
+ isCurrent: (wc) => slot.getWebContentsId() === wc.id
5354
+ });
5355
+ const slot = createHostSlotView(
5356
+ reconciler,
5357
+ {
5358
+ viewId: VIEW_ID.hostToolbar,
5359
+ layer: VIEW_LAYER.hostToolbar,
5360
+ marker: HOST_TOOLBAR_RUNTIME_MARKER,
5361
+ sessionRuntime: {
5362
+ acquire: acquireHostToolbarSessionRuntime,
5363
+ release: releaseHostToolbarSessionRuntime
5364
+ },
5365
+ portChannel: port,
5366
+ setExtentModeErrorLabel: "hostToolbar.setHeightMode"
5367
+ },
5368
+ {
5369
+ onExtentChanged: (height) => ctx.notify.hostToolbarHeightChanged(height),
5370
+ reapplyPresentOverlays: () => deps.reapplyPresentOverlays()
5371
+ }
5372
+ );
5373
+ const control = deriveSlotControl(slot.control, {
5374
+ setHeightMode: (mode) => slot.control.setExtentMode(mode)
5375
+ });
5376
+ return {
5377
+ control,
5378
+ setHostToolbarHeight: (extent) => slot.setExtent(extent),
5379
+ getHostToolbarHeight: () => slot.getExtent(),
5380
+ getHostToolbarWebContentsId: () => slot.getWebContentsId(),
5381
+ dispose: () => slot.dispose()
5382
+ };
5383
+ }
5384
+
5385
+ // src/main/services/views/host-sidebar-session-runtime.ts
5386
+ var runtime2 = createHostSlotSessionRuntime(hostSidebarRuntimePreloadPath);
5387
+ function acquireHostSidebarSessionRuntime() {
5388
+ runtime2.acquire();
5389
+ }
5390
+ function releaseHostSidebarSessionRuntime() {
5391
+ runtime2.release();
5392
+ }
5393
+
5394
+ // src/main/services/views/host-sidebar-port-channel.ts
5395
+ function createHostSidebarPortChannel(opts) {
5396
+ return createHostSlotPortChannel({
5397
+ isCurrent: opts.isCurrent,
5398
+ channel: ViewChannel.HostSidebarPort,
5399
+ logPrefix: "[host-sidebar]"
5400
+ });
5401
+ }
5402
+
5403
+ // src/main/services/views/host-sidebar-view.ts
5404
+ function createHostSidebarView(ctx, reconciler) {
5405
+ const port = createHostSidebarPortChannel({
5406
+ isCurrent: (wc) => slot.getWebContentsId() === wc.id
5407
+ });
5408
+ const slot = createHostSlotView(
5409
+ reconciler,
5410
+ {
5411
+ viewId: VIEW_ID.hostSidebar,
5412
+ layer: VIEW_LAYER.hostSidebar,
5413
+ marker: HOST_SIDEBAR_RUNTIME_MARKER,
5414
+ sessionRuntime: {
5415
+ acquire: acquireHostSidebarSessionRuntime,
5416
+ release: releaseHostSidebarSessionRuntime
5417
+ },
5418
+ portChannel: port,
5419
+ setExtentModeErrorLabel: "hostSidebar.setWidthMode"
5420
+ },
5421
+ {
5422
+ onExtentChanged: (width) => ctx.notify.hostSidebarWidthChanged(width)
5126
5423
  }
5424
+ );
5425
+ const control = deriveSlotControl(slot.control, {
5426
+ setWidthMode: (mode) => slot.control.setExtentMode(mode)
5127
5427
  });
5128
- function dispose() {
5129
- hostToolbarPort.dispose();
5130
- reconciler.destroyView(VIEW_ID.hostToolbar, hostToolbarView);
5131
- hostToolbarView = null;
5132
- if (hostToolbarRuntimeAcquired) {
5133
- releaseHostToolbarSessionRuntime();
5134
- hostToolbarRuntimeAcquired = false;
5428
+ return {
5429
+ control,
5430
+ setHostSidebarWidth: (extent) => slot.setExtent(extent),
5431
+ getHostSidebarWidth: () => slot.getExtent(),
5432
+ getHostSidebarWebContentsId: () => slot.getWebContentsId(),
5433
+ dispose: () => slot.dispose()
5434
+ };
5435
+ }
5436
+
5437
+ // src/main/services/views/host-dialog-session-runtime.ts
5438
+ var runtime3 = createHostSlotSessionRuntime(hostDialogRuntimePreloadPath);
5439
+ function acquireHostDialogSessionRuntime() {
5440
+ runtime3.acquire();
5441
+ }
5442
+ function releaseHostDialogSessionRuntime() {
5443
+ runtime3.release();
5444
+ }
5445
+
5446
+ // src/main/services/views/host-dialog-port-channel.ts
5447
+ function createHostDialogPortChannel(opts) {
5448
+ return createHostSlotPortChannel({
5449
+ isCurrent: opts.isCurrent,
5450
+ channel: ViewChannel.HostDialogPort,
5451
+ logPrefix: "[host-dialog]"
5452
+ });
5453
+ }
5454
+
5455
+ // src/main/services/views/host-dialog-view.ts
5456
+ var DEFAULT_WIDTH = 480;
5457
+ var DEFAULT_HEIGHT = 320;
5458
+ function createHostDialogView(ctx, reconciler) {
5459
+ const port = createHostDialogPortChannel({
5460
+ isCurrent: (wc) => managed.liveWebContents()?.id === wc.id
5461
+ });
5462
+ let visible = false;
5463
+ let width = DEFAULT_WIDTH;
5464
+ let height = DEFAULT_HEIGHT;
5465
+ const managed = createManagedWebContentsView({
5466
+ reconciler,
5467
+ viewId: VIEW_ID.hostDialog,
5468
+ marker: HOST_DIALOG_RUNTIME_MARKER,
5469
+ sessionRuntime: {
5470
+ acquire: acquireHostDialogSessionRuntime,
5471
+ release: releaseHostDialogSessionRuntime
5472
+ },
5473
+ port,
5474
+ onBroken: () => {
5475
+ visible = false;
5476
+ reconciler.deleteOverlayDesired(VIEW_ID.hostDialog);
5135
5477
  }
5478
+ });
5479
+ function computeBounds() {
5480
+ const [winW = 0, winH = 0] = ctx.windows.mainWindow.getContentSize();
5481
+ const w = Math.min(width, Math.max(1, winW));
5482
+ const h = Math.min(height, Math.max(1, winH));
5483
+ return {
5484
+ x: Math.max(0, Math.round((winW - w) / 2)),
5485
+ y: Math.max(0, Math.round((winH - h) / 2)),
5486
+ width: w,
5487
+ height: h
5488
+ };
5136
5489
  }
5490
+ function present() {
5491
+ reconciler.setOverlayDesired(VIEW_ID.hostDialog, {
5492
+ viewId: VIEW_ID.hostDialog,
5493
+ placement: { visible: true, bounds: computeBounds() },
5494
+ layer: VIEW_LAYER.hostDialog
5495
+ });
5496
+ reconciler.reconcileNow();
5497
+ }
5498
+ function reportMeasuredExtent(axis, extent) {
5499
+ if (!Number.isFinite(extent) || extent <= 0) return;
5500
+ if (axis === "inline") {
5501
+ width = extent;
5502
+ } else {
5503
+ height = extent;
5504
+ }
5505
+ if (visible) present();
5506
+ }
5507
+ function resetMeasuredExtent() {
5508
+ width = DEFAULT_WIDTH;
5509
+ height = DEFAULT_HEIGHT;
5510
+ if (visible) present();
5511
+ }
5512
+ const control = {
5513
+ loadURL: (url) => {
5514
+ resetMeasuredExtent();
5515
+ return managed.loadURL(url);
5516
+ },
5517
+ loadFile: (filePath) => {
5518
+ resetMeasuredExtent();
5519
+ return managed.loadFile(filePath);
5520
+ },
5521
+ get webContents() {
5522
+ return managed.liveWebContents();
5523
+ },
5524
+ setPreloadPath: (path20) => managed.setPreloadPath(path20),
5525
+ onMessage: (channel, handler) => port.onMessage(channel, handler),
5526
+ onReady: (handler) => port.onReady(handler),
5527
+ send: (channel, payload) => port.send(channel, payload),
5528
+ show() {
5529
+ managed.ensureView();
5530
+ visible = true;
5531
+ present();
5532
+ },
5533
+ hide() {
5534
+ visible = false;
5535
+ reconciler.deleteOverlayDesired(VIEW_ID.hostDialog);
5536
+ reconciler.reconcileNow();
5537
+ },
5538
+ isVisible: () => visible
5539
+ };
5540
+ reconciler.registerView(VIEW_ID.hostDialog, {
5541
+ getView: () => managed.getView(),
5542
+ ensureView: () => managed.ensureView()
5543
+ });
5137
5544
  return {
5138
5545
  control,
5139
- setHostToolbarHeight,
5140
- getHostToolbarHeight: () => hostToolbarLastHeight,
5141
- getHostToolbarWebContentsId: () => liveHostToolbarWebContents()?.id ?? null,
5142
- dispose
5546
+ reportMeasuredExtent,
5547
+ getHostDialogWebContentsId: () => managed.liveWebContents()?.id ?? null,
5548
+ reposition: () => {
5549
+ if (visible) present();
5550
+ },
5551
+ dispose: () => managed.dispose()
5143
5552
  };
5144
5553
  }
5145
5554
 
@@ -5272,6 +5681,44 @@ function createOverlayPanelsView(ctx, reconciler, deps) {
5272
5681
  pushData: (view, data) => ctx.notify.tooltipInit(view, data),
5273
5682
  readyMode: "manual"
5274
5683
  });
5684
+ function fullWindowBounds() {
5685
+ const [width = 0, height = 0] = ctx.windows.mainWindow.getContentSize();
5686
+ return { x: 0, y: 0, width: Math.max(1, width), height: Math.max(1, height) };
5687
+ }
5688
+ const projectCreateDialogPanel = createOverlayPanel({
5689
+ electron: { createWebContentsView: (opts) => new WebContentsView6(opts) },
5690
+ rendererDir: ctx.rendererDir,
5691
+ entry: "entries/project-create-dialog/index.html",
5692
+ webPreferences: {
5693
+ nodeIntegration: false,
5694
+ contextIsolation: true,
5695
+ sandbox: false,
5696
+ preload: mainPreloadPath
5697
+ },
5698
+ hardenNavigation: (wc) => applyNavigationHardening(wc, ctx.rendererDir),
5699
+ setDesired: overlayDesiredSetter(VIEW_ID.projectCreateDialog, VIEW_LAYER.dialog),
5700
+ registerView: (getView) => reconciler.registerView(VIEW_ID.projectCreateDialog, { getView }),
5701
+ destroyView: (view) => reconciler.destroyView(VIEW_ID.projectCreateDialog, view),
5702
+ pushData: (view, data) => ctx.notify.projectCreateInit(view, data),
5703
+ readyMode: "manual"
5704
+ });
5705
+ const updateDialogPanel = createOverlayPanel({
5706
+ electron: { createWebContentsView: (opts) => new WebContentsView6(opts) },
5707
+ rendererDir: ctx.rendererDir,
5708
+ entry: "entries/update-dialog/index.html",
5709
+ webPreferences: {
5710
+ nodeIntegration: false,
5711
+ contextIsolation: true,
5712
+ sandbox: false,
5713
+ preload: mainPreloadPath
5714
+ },
5715
+ hardenNavigation: (wc) => applyNavigationHardening(wc, ctx.rendererDir),
5716
+ setDesired: overlayDesiredSetter(VIEW_ID.updateDialog, VIEW_LAYER.dialog),
5717
+ registerView: (getView) => reconciler.registerView(VIEW_ID.updateDialog, { getView }),
5718
+ destroyView: (view) => reconciler.destroyView(VIEW_ID.updateDialog, view),
5719
+ pushData: (view, data) => ctx.notify.updateAvailable(view, data),
5720
+ readyMode: "manual"
5721
+ });
5275
5722
  let tooltipRequestId = 0;
5276
5723
  let activeTooltip = null;
5277
5724
  async function showSettings() {
@@ -5311,10 +5758,29 @@ function createOverlayPanelsView(ctx, reconciler, deps) {
5311
5758
  activeTooltip = null;
5312
5759
  tooltipPanel.hide();
5313
5760
  }
5761
+ function showProjectCreateDialog(data) {
5762
+ projectCreateDialogPanel.show(data, fullWindowBounds());
5763
+ }
5764
+ function hideProjectCreateDialog() {
5765
+ projectCreateDialogPanel.hide();
5766
+ }
5767
+ function showUpdateDialog(data) {
5768
+ updateDialogPanel.show(data, fullWindowBounds());
5769
+ }
5770
+ function hideUpdateDialog() {
5771
+ updateDialogPanel.hide();
5772
+ }
5773
+ function notifyUpdateDownloadProgress(percent) {
5774
+ const wc = updateDialogPanel.getWebContents();
5775
+ if (!wc) return;
5776
+ wc.send(UpdateChannel.DownloadProgress, { percent });
5777
+ }
5314
5778
  function markOverlayReady(webContentsId) {
5315
5779
  settingsPanel.markReady(webContentsId);
5316
5780
  popoverPanel.markReady(webContentsId);
5317
5781
  tooltipPanel.markReady(webContentsId);
5782
+ projectCreateDialogPanel.markReady(webContentsId);
5783
+ updateDialogPanel.markReady(webContentsId);
5318
5784
  }
5319
5785
  function applyTooltipMeasurement(webContentsId, measurement) {
5320
5786
  const active = activeTooltip;
@@ -5324,20 +5790,36 @@ function createOverlayPanelsView(ctx, reconciler, deps) {
5324
5790
  tooltipPanel.reposition(computeTooltipBounds(active.anchor, w, h, measurement));
5325
5791
  }
5326
5792
  function reapplyPresentOverlays() {
5327
- if (settingsPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.settings)) void showSettings();
5793
+ if (settingsPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.settings)) {
5794
+ showSettings().catch(() => {
5795
+ });
5796
+ }
5328
5797
  if (popoverPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.popover)) {
5329
5798
  const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
5330
5799
  popoverPanel.reposition(computePopoverBounds(w, h, overlayHeaderHeight()));
5331
5800
  }
5801
+ if (projectCreateDialogPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.projectCreateDialog)) {
5802
+ projectCreateDialogPanel.reposition(fullWindowBounds());
5803
+ }
5804
+ if (updateDialogPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.updateDialog)) {
5805
+ updateDialogPanel.reposition(fullWindowBounds());
5806
+ }
5332
5807
  }
5333
5808
  function applySettingsBoundsIfPresent() {
5334
- if (settingsPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.settings)) void showSettings();
5809
+ if (settingsPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.settings)) {
5810
+ showSettings().catch(() => {
5811
+ });
5812
+ }
5335
5813
  }
5336
5814
  function destroySettings() {
5337
5815
  activeTooltip = null;
5338
5816
  settingsPanel.destroy();
5339
5817
  tooltipPanel.destroy();
5340
5818
  }
5819
+ function destroyDialogs() {
5820
+ projectCreateDialogPanel.destroy();
5821
+ updateDialogPanel.destroy();
5822
+ }
5341
5823
  return {
5342
5824
  showSettings,
5343
5825
  hideSettings,
@@ -5348,13 +5830,21 @@ function createOverlayPanelsView(ctx, reconciler, deps) {
5348
5830
  hideTooltip,
5349
5831
  markOverlayReady,
5350
5832
  applyTooltipMeasurement,
5833
+ showProjectCreateDialog,
5834
+ hideProjectCreateDialog,
5835
+ showUpdateDialog,
5836
+ hideUpdateDialog,
5837
+ notifyUpdateDownloadProgress,
5351
5838
  reapplyPresentOverlays,
5352
5839
  applySettingsBoundsIfPresent,
5353
5840
  destroySettings,
5841
+ destroyDialogs,
5354
5842
  getSettingsWebContents: () => settingsPanel.getWebContents(),
5355
5843
  getSettingsWebContentsId: () => settingsPanel.getWebContentsId(),
5356
5844
  getPopoverWebContentsId: () => popoverPanel.getWebContentsId(),
5357
- getTooltipWebContentsId: () => tooltipPanel.getWebContentsId()
5845
+ getTooltipWebContentsId: () => tooltipPanel.getWebContentsId(),
5846
+ getProjectCreateDialogWebContentsId: () => projectCreateDialogPanel.getWebContentsId(),
5847
+ getUpdateDialogWebContentsId: () => updateDialogPanel.getWebContentsId()
5358
5848
  };
5359
5849
  }
5360
5850
 
@@ -5693,6 +6183,8 @@ function createViewManager(ctx) {
5693
6183
  const hostToolbar = createHostToolbarView(ctx, reconciler, {
5694
6184
  reapplyPresentOverlays: () => reapplyToolbarDependentOverlays()
5695
6185
  });
6186
+ const hostSidebar = createHostSidebarView(ctx, reconciler);
6187
+ const hostDialog = createHostDialogView(ctx, reconciler);
5696
6188
  const overlayPanels = createOverlayPanelsView(ctx, reconciler, {
5697
6189
  getHostToolbarHeight: hostToolbar.getHostToolbarHeight
5698
6190
  });
@@ -5713,6 +6205,9 @@ function createViewManager(ctx) {
5713
6205
  workbench.cancelWorkbenchAttachHold();
5714
6206
  disposeProjectViews();
5715
6207
  hostToolbar.dispose();
6208
+ hostSidebar.dispose();
6209
+ hostDialog.dispose();
6210
+ overlayPanels.destroyDialogs();
5716
6211
  }
5717
6212
  return {
5718
6213
  attachNativeSimulator: nativeSimulator.attachNativeSimulator,
@@ -5729,7 +6224,17 @@ function createViewManager(ctx) {
5729
6224
  hideTooltip: overlayPanels.hideTooltip,
5730
6225
  markOverlayReady: overlayPanels.markOverlayReady,
5731
6226
  applyTooltipMeasurement: overlayPanels.applyTooltipMeasurement,
5732
- repositionAll: () => overlayPanels.reapplyPresentOverlays(),
6227
+ showProjectCreateDialog: overlayPanels.showProjectCreateDialog,
6228
+ hideProjectCreateDialog: overlayPanels.hideProjectCreateDialog,
6229
+ showUpdateDialog: overlayPanels.showUpdateDialog,
6230
+ hideUpdateDialog: overlayPanels.hideUpdateDialog,
6231
+ notifyUpdateDownloadProgress: overlayPanels.notifyUpdateDownloadProgress,
6232
+ getProjectCreateDialogWebContentsId: overlayPanels.getProjectCreateDialogWebContentsId,
6233
+ getUpdateDialogWebContentsId: overlayPanels.getUpdateDialogWebContentsId,
6234
+ repositionAll: () => {
6235
+ overlayPanels.reapplyPresentOverlays();
6236
+ hostDialog.reposition();
6237
+ },
5733
6238
  disposeProjectViews,
5734
6239
  disposeAll,
5735
6240
  getSimulatorWebContentsId: nativeSimulator.getSimulatorWebContentsId,
@@ -5743,6 +6248,7 @@ function createViewManager(ctx) {
5743
6248
  getHostToolbarHeight: hostToolbar.getHostToolbarHeight,
5744
6249
  resize: () => overlayPanels.applySettingsBoundsIfPresent(),
5745
6250
  setPlacementSnapshot: reconciler.setPlacementSnapshot,
6251
+ allocatePlacementGeneration: reconciler.allocateGeneration,
5746
6252
  attachWorkbench: workbench.attachWorkbench,
5747
6253
  setWorkbenchSource: workbench.setWorkbenchSource,
5748
6254
  detachWorkbench: workbench.detachWorkbench,
@@ -5750,7 +6256,14 @@ function createViewManager(ctx) {
5750
6256
  holdWorkbenchAttach: workbench.holdWorkbenchAttach,
5751
6257
  cancelWorkbenchAttachHold: workbench.cancelWorkbenchAttachHold,
5752
6258
  setHostToolbarHeight: hostToolbar.setHostToolbarHeight,
5753
- hostToolbar: hostToolbar.control
6259
+ hostToolbar: hostToolbar.control,
6260
+ getHostSidebarWebContentsId: hostSidebar.getHostSidebarWebContentsId,
6261
+ getHostSidebarWidth: hostSidebar.getHostSidebarWidth,
6262
+ setHostSidebarWidth: hostSidebar.setHostSidebarWidth,
6263
+ hostSidebar: hostSidebar.control,
6264
+ getHostDialogWebContentsId: hostDialog.getHostDialogWebContentsId,
6265
+ reportHostDialogMeasuredExtent: hostDialog.reportMeasuredExtent,
6266
+ hostDialog: hostDialog.control
5754
6267
  };
5755
6268
  }
5756
6269
 
@@ -5885,6 +6398,29 @@ import { app as app6 } from "electron";
5885
6398
  import path9 from "path";
5886
6399
  import fs5 from "fs";
5887
6400
  var log2 = createLogger("projects");
6401
+ function readProjectConfig(dirPath) {
6402
+ let merged = {};
6403
+ for (const fileName of ["project.config.json", "project.private.config.json"]) {
6404
+ const configPath = path9.join(dirPath, fileName);
6405
+ if (!fs5.existsSync(configPath)) continue;
6406
+ try {
6407
+ merged = { ...merged, ...JSON.parse(fs5.readFileSync(configPath, "utf-8")) };
6408
+ } catch (err2) {
6409
+ log2.warn(`Failed to parse ${configPath}`, err2);
6410
+ }
6411
+ }
6412
+ return merged;
6413
+ }
6414
+ function detectRuntimeType(dirPath) {
6415
+ const compileType = readProjectConfig(dirPath).compileType;
6416
+ if (compileType === "game") return "minigame";
6417
+ if (compileType === "miniprogram") return "miniprogram";
6418
+ const hasMiniProgramConfig = fs5.existsSync(path9.join(dirPath, "app.json"));
6419
+ const hasMiniGameConfig = fs5.existsSync(path9.join(dirPath, "game.json"));
6420
+ const hasMiniGameEntry = ["game.js", "game.ts"].some((fileName) => fs5.existsSync(path9.join(dirPath, fileName)));
6421
+ if (!hasMiniProgramConfig && hasMiniGameConfig && hasMiniGameEntry) return "minigame";
6422
+ return "miniprogram";
6423
+ }
5888
6424
  function getProjectsFile() {
5889
6425
  return path9.join(app6.getPath("userData"), "dimina-projects.json");
5890
6426
  }
@@ -5908,6 +6444,12 @@ function validateProjectDir(dirPath) {
5908
6444
  if (!fs5.existsSync(dirPath)) {
5909
6445
  return `\u5C0F\u7A0B\u5E8F\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${dirPath}`;
5910
6446
  }
6447
+ if (detectRuntimeType(dirPath) === "minigame") {
6448
+ if (!fs5.existsSync(path9.join(dirPath, "game.json"))) {
6449
+ return "\u8BE5\u76EE\u5F55\u7F3A\u5C11 game.json\uFF0C\u8BF7\u9009\u62E9\u5305\u542B\u5C0F\u6E38\u620F\u6E90\u7801\u7684\u76EE\u5F55";
6450
+ }
6451
+ return null;
6452
+ }
5911
6453
  if (!fs5.existsSync(path9.join(dirPath, "app.json"))) {
5912
6454
  const configPath = path9.join(dirPath, "project.config.json");
5913
6455
  if (fs5.existsSync(configPath)) {
@@ -5940,10 +6482,11 @@ function addProject(dirPath) {
5940
6482
  } catch (err2) {
5941
6483
  log2.warn("Failed to read project name from config", err2);
5942
6484
  }
5943
- const project = { name, path: dirPath, lastOpened: null };
6485
+ const type = detectRuntimeType(dirPath);
6486
+ const project = { name, path: dirPath, lastOpened: null, type };
5944
6487
  const idx = projects.findIndex((p) => p.path === dirPath);
5945
6488
  if (idx >= 0) {
5946
- projects[idx] = { ...projects[idx], name };
6489
+ projects[idx] = { ...projects[idx], name, type };
5947
6490
  } else {
5948
6491
  projects.unshift(project);
5949
6492
  }
@@ -5964,13 +6507,17 @@ function updateLastOpened(dirPath) {
5964
6507
  function getCompileConfig(dirPath) {
5965
6508
  const projects = load();
5966
6509
  const project = projects.find((p) => p.path === dirPath);
5967
- return project?.compileConfig ?? {
5968
- startPage: "",
6510
+ if (project?.compileConfig) return project.compileConfig;
6511
+ return {
6512
+ startPage: getProjectPages(dirPath).entryPagePath,
5969
6513
  scene: DEFAULT_SCENE,
5970
6514
  queryParams: []
5971
6515
  };
5972
6516
  }
5973
6517
  function getProjectPages(dirPath) {
6518
+ if (detectRuntimeType(dirPath) === "minigame") {
6519
+ return { pages: ["game"], entryPagePath: "game" };
6520
+ }
5974
6521
  const appJsonPath = path9.join(dirPath, "app.json");
5975
6522
  try {
5976
6523
  const appJson = JSON.parse(
@@ -6800,6 +7347,19 @@ var TooltipMeasuredSchema = z3.tuple([
6800
7347
  height: z3.number().finite().positive()
6801
7348
  })
6802
7349
  ]);
7350
+ var ProjectCreateShowSchema = z3.tuple([
7351
+ z3.object({
7352
+ templates: z3.array(z3.looseObject({})),
7353
+ defaultBaseDir: z3.string()
7354
+ })
7355
+ ]);
7356
+ var ProjectCreateSubmitSchema = z3.tuple([
7357
+ z3.object({
7358
+ name: z3.string().min(1),
7359
+ path: AbsolutePath,
7360
+ templateId: z3.string().min(1)
7361
+ })
7362
+ ]);
6803
7363
  var SimWidth = z3.number().int().min(100).max(2e3);
6804
7364
  var SimulatorAttachNativeSchema = z3.tuple([
6805
7365
  z3.string().url().refine((u) => u.startsWith("http://") || u.startsWith("https://"), {
@@ -6865,6 +7425,18 @@ var HostToolbarAdvertiseHeightSchema = z3.tuple([
6865
7425
  extent: NonNegInt
6866
7426
  })
6867
7427
  ]);
7428
+ var HostSidebarAdvertiseWidthSchema = z3.tuple([
7429
+ z3.object({
7430
+ axis: z3.literal("inline"),
7431
+ extent: NonNegInt
7432
+ })
7433
+ ]);
7434
+ var HostDialogAdvertiseSizeSchema = z3.tuple([
7435
+ z3.object({
7436
+ axis: z3.union([z3.literal("block"), z3.literal("inline")]),
7437
+ extent: NonNegInt
7438
+ })
7439
+ ]);
6868
7440
  var SimulatorCustomApiInvokeSchema = z3.tuple([
6869
7441
  z3.string().min(1).max(256),
6870
7442
  z3.unknown()
@@ -6968,6 +7540,20 @@ function registerTooltipIpc(ctx) {
6968
7540
  });
6969
7541
  }
6970
7542
 
7543
+ // src/main/ipc/project-create.ts
7544
+ function registerProjectCreateIpc(ctx) {
7545
+ return new IpcRegistry(ctx.senderPolicy).on(ProjectCreateChannel.Show, (_event, ...args) => {
7546
+ const [data] = validate(ProjectCreateChannel.Show, ProjectCreateShowSchema, args);
7547
+ ctx.views.showProjectCreateDialog(data);
7548
+ }).on(ProjectCreateChannel.Cancel, () => {
7549
+ ctx.views.hideProjectCreateDialog();
7550
+ }).on(ProjectCreateChannel.Submit, (_event, ...args) => {
7551
+ const [input] = validate(ProjectCreateChannel.Submit, ProjectCreateSubmitSchema, args);
7552
+ ctx.views.hideProjectCreateDialog();
7553
+ ctx.notify.projectCreateSubmitted(input);
7554
+ });
7555
+ }
7556
+
6971
7557
  // src/main/ipc/projects.ts
6972
7558
  import { app as app8, dialog } from "electron";
6973
7559
  import path13 from "path";
@@ -7087,6 +7673,9 @@ function registerProjectsIpc(ctx) {
7087
7673
  buttons: ["\u786E\u5B9A"]
7088
7674
  });
7089
7675
  }
7676
+ const importedCategory = project.type ?? "miniprogram";
7677
+ ctx.notify.hostSidebarCategorySelected(importedCategory);
7678
+ ctx.views.hostSidebar.send("project-category-forced", { category: importedCategory });
7090
7679
  return project;
7091
7680
  }).handle(ProjectsChannel.Remove, (_event, ...args) => {
7092
7681
  const [dirPath] = validate(ProjectsChannel.Remove, ProjectsRemoveSchema, args);
@@ -7253,13 +7842,13 @@ function registerSettingsIpc(ctx) {
7253
7842
  };
7254
7843
  }).handle(WorkbenchSettingsChannel.GetMcpStatus, () => {
7255
7844
  const settings = loadWorkbenchSettings();
7256
- const runtime = getMcpStatus();
7845
+ const runtime4 = getMcpStatus();
7257
7846
  return {
7258
7847
  configured: settings.mcp.enabled,
7259
7848
  configuredPort: settings.mcp.port,
7260
- running: runtime.running,
7261
- activePort: runtime.port,
7262
- error: runtime.error
7849
+ running: runtime4.running,
7850
+ activePort: runtime4.port,
7851
+ error: runtime4.error
7263
7852
  };
7264
7853
  }).handle(SettingsChannel.SetVisible, async (_, ...args) => {
7265
7854
  const [visible] = validate(SettingsChannel.SetVisible, SettingsSetVisibleSchema, args);
@@ -7307,6 +7896,76 @@ function registerInternalDevtoolsIpc(ctx) {
7307
7896
  });
7308
7897
  }
7309
7898
 
7899
+ // src/main/ipc/views.ts
7900
+ import { ipcMain as ipcMain3 } from "electron";
7901
+ function registerViewsIpc(ctx) {
7902
+ const registry = new IpcRegistry(ctx.senderPolicy).handle(ViewChannel.AllocatePlacementGeneration, () => ctx.views.allocatePlacementGeneration()).handle(ViewChannel.PlacementSnapshot, (_event, ...args) => {
7903
+ const [snapshot] = validate(
7904
+ ViewChannel.PlacementSnapshot,
7905
+ PlacementSnapshotSchema,
7906
+ args
7907
+ );
7908
+ ctx.views.setPlacementSnapshot(snapshot);
7909
+ }).handle(ViewChannel.HostToolbarGetHeight, () => ctx.views.getHostToolbarHeight()).handle(ViewChannel.HostSidebarGetWidth, () => ctx.views.getHostSidebarWidth());
7910
+ const onAdvertiseHeight = (event, ...args) => {
7911
+ if (event.sender.id !== ctx.views.getHostToolbarWebContentsId()) return;
7912
+ let extent;
7913
+ try {
7914
+ ;
7915
+ [{ extent }] = validate(
7916
+ ViewChannel.HostToolbarAdvertiseHeight,
7917
+ HostToolbarAdvertiseHeightSchema,
7918
+ args
7919
+ );
7920
+ } catch {
7921
+ return;
7922
+ }
7923
+ ctx.views.setHostToolbarHeight(extent);
7924
+ };
7925
+ ipcMain3.on(ViewChannel.HostToolbarAdvertiseHeight, onAdvertiseHeight);
7926
+ const onAdvertiseWidth = (event, ...args) => {
7927
+ if (event.sender.id !== ctx.views.getHostSidebarWebContentsId()) return;
7928
+ let extent;
7929
+ try {
7930
+ ;
7931
+ [{ extent }] = validate(
7932
+ ViewChannel.HostSidebarAdvertiseWidth,
7933
+ HostSidebarAdvertiseWidthSchema,
7934
+ args
7935
+ );
7936
+ } catch {
7937
+ return;
7938
+ }
7939
+ ctx.views.setHostSidebarWidth(extent);
7940
+ };
7941
+ ipcMain3.on(ViewChannel.HostSidebarAdvertiseWidth, onAdvertiseWidth);
7942
+ const onAdvertiseDialogSize = (event, ...args) => {
7943
+ if (event.sender.id !== ctx.views.getHostDialogWebContentsId()) return;
7944
+ let axis;
7945
+ let extent;
7946
+ try {
7947
+ ;
7948
+ [{ axis, extent }] = validate(
7949
+ ViewChannel.HostDialogAdvertiseSize,
7950
+ HostDialogAdvertiseSizeSchema,
7951
+ args
7952
+ );
7953
+ } catch {
7954
+ return;
7955
+ }
7956
+ ctx.views.reportHostDialogMeasuredExtent(axis, extent);
7957
+ };
7958
+ ipcMain3.on(ViewChannel.HostDialogAdvertiseSize, onAdvertiseDialogSize);
7959
+ return {
7960
+ dispose() {
7961
+ void registry.dispose();
7962
+ ipcMain3.removeListener(ViewChannel.HostToolbarAdvertiseHeight, onAdvertiseHeight);
7963
+ ipcMain3.removeListener(ViewChannel.HostSidebarAdvertiseWidth, onAdvertiseWidth);
7964
+ ipcMain3.removeListener(ViewChannel.HostDialogAdvertiseSize, onAdvertiseDialogSize);
7965
+ }
7966
+ };
7967
+ }
7968
+
7310
7969
  // src/main/ipc/simulator-module.ts
7311
7970
  import { DisposableRegistry as DisposableRegistry3 } from "@dimina-kit/electron-deck/main";
7312
7971
 
@@ -7341,47 +8000,11 @@ function installBridgeRouter(ctx) {
7341
8000
  installRuntimeBridgeRouter(ctx);
7342
8001
  }
7343
8002
 
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
8003
  // src/main/ipc/simulator-module.ts
7380
8004
  var simulatorModule = {
7381
8005
  setup: (ctx) => {
7382
8006
  const reg = new DisposableRegistry3();
7383
8007
  reg.add(registerSimulatorIpc(ctx));
7384
- reg.add(registerViewsIpc(ctx));
7385
8008
  installBridgeRouter(ctx);
7386
8009
  return reg;
7387
8010
  }
@@ -10025,7 +10648,9 @@ async function startWorkbenchCoiServer(options) {
10025
10648
  import { app as app11, shell as shell3 } from "electron";
10026
10649
  var UpdateManager = class {
10027
10650
  checker;
10028
- mainWindow;
10651
+ showUpdatePanel;
10652
+ notifyDownloadProgress;
10653
+ hideUpdatePanel;
10029
10654
  getCurrentVersion;
10030
10655
  latestUpdate = null;
10031
10656
  downloadedPath = null;
@@ -10042,16 +10667,26 @@ var UpdateManager = class {
10042
10667
  timer = null;
10043
10668
  initialTimer = null;
10044
10669
  ipc;
10670
+ /**
10671
+ * Set by `dispose()`. Clearing the timers only stops FUTURE ticks — an
10672
+ * in-flight `checkAndNotify()` invocation (already past its `await
10673
+ * this.check()`) has no timer left to cancel it, and would otherwise call
10674
+ * `showUpdatePanel` after dispose has torn down the overlay panel that
10675
+ * owns (e.g. `views.disposeAll()` destroying its WebContentsView).
10676
+ */
10677
+ disposed = false;
10045
10678
  constructor(opts) {
10046
10679
  this.checker = opts.checker;
10047
- this.mainWindow = opts.mainWindow;
10680
+ this.showUpdatePanel = opts.showUpdatePanel;
10681
+ this.notifyDownloadProgress = opts.notifyDownloadProgress;
10682
+ this.hideUpdatePanel = opts.hideUpdatePanel;
10048
10683
  this.getCurrentVersion = opts.getCurrentVersion ?? (() => app11.getVersion());
10049
10684
  this.ipc = new IpcRegistry(opts.senderPolicy);
10050
10685
  this.registerIpc();
10051
10686
  this.startPeriodicCheck(opts.checkInterval ?? 60 * 60 * 1e3, opts.initialDelay ?? 5e3);
10052
10687
  }
10053
10688
  registerIpc() {
10054
- this.ipc.handle(UpdateChannel.Check, async () => this.check()).handle(UpdateChannel.Download, async () => this.download()).handle(UpdateChannel.Install, async () => this.install());
10689
+ 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
10690
  }
10056
10691
  async check() {
10057
10692
  try {
@@ -10075,7 +10710,7 @@ var UpdateManager = class {
10075
10710
  }
10076
10711
  try {
10077
10712
  const filePath = await this.checker.downloadUpdate(this.latestUpdate, (percent) => {
10078
- this.mainWindow.webContents.send(UpdateChannel.DownloadProgress, { percent });
10713
+ this.notifyDownloadProgress(percent);
10079
10714
  });
10080
10715
  this.downloadedPath = filePath;
10081
10716
  return { success: true, filePath };
@@ -10103,6 +10738,7 @@ var UpdateManager = class {
10103
10738
  * the timer clears + handler removals are scheduled synchronously.
10104
10739
  */
10105
10740
  dispose() {
10741
+ this.disposed = true;
10106
10742
  if (this.timer) {
10107
10743
  clearInterval(this.timer);
10108
10744
  this.timer = null;
@@ -10119,10 +10755,11 @@ var UpdateManager = class {
10119
10755
  }
10120
10756
  async checkAndNotify() {
10121
10757
  const result = await this.check();
10758
+ if (this.disposed) return;
10122
10759
  if (!result.hasUpdate || !result.info) return;
10123
10760
  if (this.hasNotified) return;
10124
10761
  this.hasNotified = true;
10125
- this.mainWindow.webContents.send(UpdateChannel.Available, result.info);
10762
+ this.showUpdatePanel(result.info);
10126
10763
  }
10127
10764
  };
10128
10765
 
@@ -10564,7 +11201,7 @@ function enableDevRendererAutoReload(rendererDir2) {
10564
11201
  const watcher = fs10.watch(rendererDir2, { recursive: true }, () => {
10565
11202
  if (reloadTimer) clearTimeout(reloadTimer);
10566
11203
  reloadTimer = setTimeout(() => {
10567
- for (const win of BrowserWindow6.getAllWindows()) {
11204
+ for (const win of BrowserWindow5.getAllWindows()) {
10568
11205
  win.webContents.reload();
10569
11206
  }
10570
11207
  }, 300);
@@ -10604,6 +11241,8 @@ async function createDevtoolsRuntime(config = {}, onInstanceCreated) {
10604
11241
  context.registry.add(toDisposable5(() => context.internalDevtoolsWindow?.dispose()));
10605
11242
  context.registry.add(registerInternalDevtoolsIpc(context));
10606
11243
  context.registry.add(registerTooltipIpc(context));
11244
+ context.registry.add(registerProjectCreateIpc(context));
11245
+ context.registry.add(registerViewsIpc(context));
10607
11246
  context.registry.add((0, simulator_session_policy_exports.setupSimulatorSessionPolicy)());
10608
11247
  context.registry.add(installThemeBackgroundSync());
10609
11248
  if (!config.adapter) context.registry.add(setupCompileWorkerStandby(context));
@@ -10656,13 +11295,27 @@ async function createDevtoolsRuntime(config = {}, onInstanceCreated) {
10656
11295
  instance.registerSimulatorApi("login", async () => {
10657
11296
  return "hello";
10658
11297
  });
11298
+ context.registry.add(
11299
+ context.views.hostSidebar.onMessage("project-category-selected", (payload) => {
11300
+ const category = payload?.category;
11301
+ if (category !== "miniprogram" && category !== "minigame") return;
11302
+ context.notify.hostSidebarCategorySelected(category);
11303
+ })
11304
+ );
11305
+ context.views.hostSidebar.loadFile(path19.join(rendererDir2, "entries/host-sidebar-default/index.html")).catch((err2) => {
11306
+ console.warn("[workbench] failed to load host-sidebar default content:", err2);
11307
+ });
11308
+ context.views.hostSidebar.setWidthMode({ fixed: HOST_SIDEBAR_DEFAULT_WIDTH });
11309
+ context.views.hostSidebar.setWidthMode("auto");
10659
11310
  if (config.onSetup) {
10660
11311
  await config.onSetup(instance);
10661
11312
  }
10662
11313
  if (config.updateChecker) {
10663
11314
  instance.updateManager = new UpdateManager({
10664
11315
  checker: config.updateChecker,
10665
- mainWindow,
11316
+ showUpdatePanel: (info) => context.views.showUpdateDialog(info),
11317
+ notifyDownloadProgress: (percent) => context.views.notifyUpdateDownloadProgress(percent),
11318
+ hideUpdatePanel: () => context.views.hideUpdateDialog(),
10666
11319
  senderPolicy: context.senderPolicy,
10667
11320
  checkInterval: config.updateOptions?.checkInterval,
10668
11321
  initialDelay: config.updateOptions?.initialDelay,