@dimina-kit/devtools 0.4.0-dev.20260831134112 → 0.4.0-dev.20260907055341

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 (275) hide show
  1. package/README.md +52 -729
  2. package/dist/main/app/app.d.ts +27 -7
  3. package/dist/main/app/app.js +285 -681
  4. package/dist/main/app/editor-view.d.ts +21 -0
  5. package/dist/main/app/editor-view.js +71 -0
  6. package/dist/main/app/global-mirrors.d.ts +23 -0
  7. package/dist/main/app/global-mirrors.js +37 -0
  8. package/dist/main/app/host-sidebar-default.d.ts +19 -0
  9. package/dist/main/app/host-sidebar-default.js +44 -0
  10. package/dist/main/app/menu-setup.d.ts +13 -0
  11. package/dist/main/app/menu-setup.js +49 -0
  12. package/dist/main/app/open-project-ipc.d.ts +13 -0
  13. package/dist/main/app/open-project-ipc.js +21 -0
  14. package/dist/main/app/project-list-surface.d.ts +31 -0
  15. package/dist/main/app/project-list-surface.js +20 -0
  16. package/dist/main/app/project-window.d.ts +36 -0
  17. package/dist/main/app/project-window.js +93 -0
  18. package/dist/main/app/servers.d.ts +17 -0
  19. package/dist/main/app/servers.js +60 -0
  20. package/dist/main/app/ui-extension-targets.d.ts +42 -0
  21. package/dist/main/app/ui-extension-targets.js +101 -0
  22. package/dist/main/app/window-close-reveal.harness.d.ts +34 -0
  23. package/dist/main/app/window-close-reveal.harness.js +65 -0
  24. package/dist/main/app/window-events.d.ts +15 -0
  25. package/dist/main/app/window-events.js +45 -0
  26. package/dist/main/app/window-runtime-services.d.ts +41 -0
  27. package/dist/main/app/window-runtime-services.js +178 -0
  28. package/dist/main/app/workbench-modules.d.ts +24 -0
  29. package/dist/main/app/workbench-modules.js +51 -0
  30. package/dist/main/app/workbench-window.d.ts +85 -0
  31. package/dist/main/app/workbench-window.js +310 -0
  32. package/dist/main/index.bundle.js +10669 -9096
  33. package/dist/main/ipc/app.d.ts +4 -1
  34. package/dist/main/ipc/app.js +4 -3
  35. package/dist/main/ipc/device-picker.d.ts +16 -0
  36. package/dist/main/ipc/device-picker.js +27 -0
  37. package/dist/main/ipc/index.d.ts +1 -0
  38. package/dist/main/ipc/index.js +1 -0
  39. package/dist/main/ipc/internal-devtools.d.ts +2 -1
  40. package/dist/main/ipc/internal-devtools.js +4 -3
  41. package/dist/main/ipc/popover.d.ts +4 -1
  42. package/dist/main/ipc/popover.js +25 -9
  43. package/dist/main/ipc/project-create.d.ts +2 -1
  44. package/dist/main/ipc/project-create.js +6 -5
  45. package/dist/main/ipc/project-fs.d.ts +3 -1
  46. package/dist/main/ipc/project-fs.js +17 -17
  47. package/dist/main/ipc/projects.d.ts +3 -3
  48. package/dist/main/ipc/projects.js +13 -12
  49. package/dist/main/ipc/session.d.ts +4 -1
  50. package/dist/main/ipc/session.js +16 -11
  51. package/dist/main/ipc/settings.d.ts +4 -1
  52. package/dist/main/ipc/settings.js +12 -19
  53. package/dist/main/ipc/simulator-module.d.ts +5 -0
  54. package/dist/main/ipc/simulator-module.js +9 -5
  55. package/dist/main/ipc/simulator.d.ts +4 -1
  56. package/dist/main/ipc/simulator.js +12 -18
  57. package/dist/main/ipc/tooltip.d.ts +2 -1
  58. package/dist/main/ipc/tooltip.js +8 -7
  59. package/dist/main/ipc/views.d.ts +4 -1
  60. package/dist/main/ipc/views.js +20 -9
  61. package/dist/main/runtime/devtools-backend-before-quit.harness.d.ts +2 -20
  62. package/dist/main/runtime/devtools-backend-before-quit.harness.js +14 -283
  63. package/dist/main/runtime/devtools-backend.js +14 -3
  64. package/dist/main/runtime/devtools-runtime-mock.harness.d.ts +21 -0
  65. package/dist/main/runtime/devtools-runtime-mock.harness.js +313 -0
  66. package/dist/main/services/app-services.d.ts +62 -0
  67. package/dist/main/services/app-services.js +64 -0
  68. package/dist/main/services/automation/connection-target.d.ts +36 -0
  69. package/dist/main/services/automation/connection-target.js +29 -0
  70. package/dist/main/services/automation/console-bridge.d.ts +28 -0
  71. package/dist/main/services/automation/console-bridge.js +91 -0
  72. package/dist/main/services/automation/handlers/app.js +4 -4
  73. package/dist/main/services/automation/handlers/element.js +55 -21
  74. package/dist/main/services/automation/index.d.ts +12 -1
  75. package/dist/main/services/automation/index.js +54 -133
  76. package/dist/main/services/default-adapter.js +1 -1
  77. package/dist/main/services/fs-bridge-protocol.d.ts +61 -0
  78. package/dist/main/services/fs-bridge-protocol.js +34 -0
  79. package/dist/main/services/fs-watch-sse.d.ts +8 -1
  80. package/dist/main/services/fs-watch-sse.js +19 -5
  81. package/dist/main/services/mcp/connection-owner.d.ts +38 -0
  82. package/dist/main/services/mcp/connection-owner.js +79 -0
  83. package/dist/main/services/mcp/index.d.ts +3 -1
  84. package/dist/main/services/mcp/index.js +4 -3
  85. package/dist/main/services/mcp/opened-project.d.ts +88 -0
  86. package/dist/main/services/mcp/opened-project.js +60 -0
  87. package/dist/main/services/mcp/target-manager.d.ts +71 -23
  88. package/dist/main/services/mcp/target-manager.js +269 -142
  89. package/dist/main/services/mcp/target-selection.d.ts +47 -0
  90. package/dist/main/services/mcp/target-selection.js +71 -0
  91. package/dist/main/services/mcp/tools/context-tools.js +20 -5
  92. package/dist/main/services/mcp/tools/project-tools.d.ts +29 -6
  93. package/dist/main/services/mcp/tools/project-tools.js +37 -25
  94. package/dist/main/services/module.d.ts +13 -5
  95. package/dist/main/services/notifications/renderer-notifier.d.ts +28 -4
  96. package/dist/main/services/notifications/renderer-notifier.js +15 -3
  97. package/dist/main/services/projects/local-provider.js +2 -0
  98. package/dist/main/services/projects/project-repository.d.ts +31 -1
  99. package/dist/main/services/projects/project-repository.js +144 -20
  100. package/dist/main/services/projects/types.d.ts +31 -8
  101. package/dist/main/services/safe-area/index.d.ts +19 -5
  102. package/dist/main/services/safe-area/index.js +38 -13
  103. package/dist/main/services/simulator/ui-extensions.d.ts +8 -0
  104. package/dist/main/services/simulator/ui-extensions.js +16 -6
  105. package/dist/main/services/simulator-storage/index.d.ts +12 -1
  106. package/dist/main/services/simulator-storage/index.js +22 -7
  107. package/dist/main/services/simulator-storage/window-scope.d.ts +20 -0
  108. package/dist/main/services/simulator-storage/window-scope.js +20 -0
  109. package/dist/main/services/views/host-slot-port-channel.d.ts +20 -3
  110. package/dist/main/services/views/host-slot-port-channel.js +33 -5
  111. package/dist/main/services/views/managed-web-contents-view.js +21 -1
  112. package/dist/main/services/views/native-simulator-view.js +13 -16
  113. package/dist/main/services/views/overlay-panels-view.d.ts +13 -0
  114. package/dist/main/services/views/overlay-panels-view.js +31 -0
  115. package/dist/main/services/views/view-manager.d.ts +1 -1
  116. package/dist/main/services/views/view-manager.js +3 -0
  117. package/dist/main/services/window-contexts/context-router.d.ts +36 -0
  118. package/dist/main/services/window-contexts/context-router.js +55 -0
  119. package/dist/main/services/workbench-coi-host.d.ts +52 -0
  120. package/dist/main/services/workbench-coi-host.js +227 -0
  121. package/dist/main/services/workbench-coi-server.js +75 -133
  122. package/dist/main/services/workbench-coi-shutdown.d.ts +40 -0
  123. package/dist/main/services/workbench-coi-shutdown.js +69 -0
  124. package/dist/main/services/workbench-coi-static.d.ts +23 -0
  125. package/dist/main/services/workbench-coi-static.js +87 -0
  126. package/dist/main/services/workbench-context.d.ts +27 -3
  127. package/dist/main/services/workbench-context.js +10 -5
  128. package/dist/main/services/workspace/compile-mode-adapter.d.ts +18 -0
  129. package/dist/main/services/workspace/compile-mode-adapter.js +57 -0
  130. package/dist/main/services/workspace/compile-mode-store.d.ts +25 -0
  131. package/dist/main/services/workspace/compile-mode-store.js +71 -0
  132. package/dist/main/services/workspace/workspace-compile-modes.d.ts +59 -0
  133. package/dist/main/services/workspace/workspace-compile-modes.js +93 -0
  134. package/dist/main/services/workspace/workspace-referer.d.ts +17 -0
  135. package/dist/main/services/workspace/workspace-referer.js +26 -0
  136. package/dist/main/services/workspace/workspace-service.d.ts +4 -0
  137. package/dist/main/services/workspace/workspace-service.js +51 -84
  138. package/dist/main/services/workspace/workspace-thumbnails.d.ts +22 -0
  139. package/dist/main/services/workspace/workspace-thumbnails.js +67 -0
  140. package/dist/main/utils/ipc-context-source.d.ts +40 -0
  141. package/dist/main/utils/ipc-context-source.js +23 -0
  142. package/dist/main/utils/ipc-registry.d.ts +42 -36
  143. package/dist/main/utils/ipc-registry.js +117 -50
  144. package/dist/main/utils/sender-policy.d.ts +9 -0
  145. package/dist/main/utils/sender-policy.js +26 -3
  146. package/dist/main/utils/theme.d.ts +3 -2
  147. package/dist/main/utils/theme.js +3 -2
  148. package/dist/main/windows/main-window/create.d.ts +16 -0
  149. package/dist/main/windows/main-window/create.js +19 -11
  150. package/dist/main/windows/main-window/events.d.ts +1 -1
  151. package/dist/main/windows/main-window/events.js +26 -13
  152. package/dist/main/windows/main-window/index.d.ts +1 -1
  153. package/dist/main/windows/main-window/index.js +1 -1
  154. package/dist/native-host/common/common.js +94 -73
  155. package/dist/native-host/render/render.js +4079 -3171
  156. package/dist/native-host/service/service.js +2 -2
  157. package/dist/preload/runtime/native-host.d.ts +4 -0
  158. package/dist/preload/runtime/temp-files.js +9 -2
  159. package/dist/preload/runtime/wait-for-slot-root.d.ts +7 -4
  160. package/dist/preload/runtime/wait-for-slot-root.js +36 -8
  161. package/dist/preload/windows/host-dialog-runtime.cjs +10 -3
  162. package/dist/preload/windows/host-dialog-runtime.cjs.map +2 -2
  163. package/dist/preload/windows/host-sidebar-runtime.cjs +10 -3
  164. package/dist/preload/windows/host-sidebar-runtime.cjs.map +2 -2
  165. package/dist/preload/windows/host-toolbar-runtime.cjs +10 -3
  166. package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
  167. package/dist/preload/windows/main.cjs +181 -4
  168. package/dist/preload/windows/main.cjs.map +4 -4
  169. package/dist/preload/windows/simulator.cjs +10 -0
  170. package/dist/preload/windows/simulator.cjs.map +2 -2
  171. package/dist/preload/windows/simulator.js +10 -0
  172. package/dist/renderer/assets/button-CB2MWjHY.js +2 -0
  173. package/dist/renderer/assets/constants-CkoGPQTS.js +2 -0
  174. package/dist/renderer/assets/constants-zQZ2-y21.js +2 -0
  175. package/dist/renderer/assets/{createLucideIcon-Bqi8hpdi.js → createLucideIcon-cZ9FlZZw.js} +2 -2
  176. package/dist/renderer/assets/devicePicker-H2eIO4e1.js +2 -0
  177. package/dist/renderer/assets/dialog-pHzEA8Vx.js +46 -0
  178. package/dist/renderer/assets/dist-B5HADirS.js +2 -0
  179. package/dist/renderer/assets/{dist-DKWdE1TK.js → dist-DIFlRMKe.js} +2 -2
  180. package/dist/renderer/assets/hostSidebarDefault-DRWh6OCt.js +2 -0
  181. package/dist/renderer/assets/index-CEL_XFge.js +2 -0
  182. package/dist/renderer/assets/{input-Ct3alvkq.js → input-CAObw95L.js} +2 -2
  183. package/dist/renderer/assets/ipc-channels-overlays-gIPUFnqc.js +2 -0
  184. package/dist/renderer/assets/jsx-runtime-DICEQH_0.css +1 -0
  185. package/dist/renderer/assets/{jsx-runtime-DGLHmmOq.js → jsx-runtime-DIw5wnYl.js} +1 -1
  186. package/dist/renderer/assets/plus-BQ9u5EbL.js +2 -0
  187. package/dist/renderer/assets/popover-Cw7G2Ctp.js +2 -0
  188. package/dist/renderer/assets/presets-DMZOb9ay.js +2 -0
  189. package/dist/renderer/assets/project-api-YTOr_Yvo.js +2 -0
  190. package/dist/renderer/assets/{projectCreateDialog-Bbjz75bP.js → projectCreateDialog-BmLqiYxn.js} +2 -2
  191. package/dist/renderer/assets/search-BMvuYF48.js +2 -0
  192. package/dist/renderer/assets/select-nFP95TxM.js +2 -0
  193. package/dist/renderer/assets/settings-CnpVfSWt.js +2 -0
  194. package/dist/renderer/assets/settings-api-Ccsf-Nsj.js +2 -0
  195. package/dist/renderer/assets/settings-tab-bar-CAzrv32m.js +2 -0
  196. package/dist/renderer/assets/smartphone-Bb2GdIKy.js +2 -0
  197. package/dist/renderer/assets/tabs-CPKN3Mmq.js +2 -0
  198. package/dist/renderer/assets/{tooltip-B_-_YVbw.js → tooltip-D6AxXRk5.js} +2 -2
  199. package/dist/renderer/assets/types-Bh0hA7El.js +2 -0
  200. package/dist/renderer/assets/updateDialog-CwndJ0Bl.js +2 -0
  201. package/dist/renderer/assets/{utils-kfQov6Pa.js → utils-sEB5OZEQ.js} +2 -2
  202. package/dist/renderer/assets/view-api-B-2zPBR5.js +2 -0
  203. package/dist/renderer/assets/view-ids-BfaDVV5P.js +2 -0
  204. package/dist/renderer/assets/workbench-BLJ0wKsg.js +5 -0
  205. package/dist/renderer/assets/{workbenchSettings-CV4LVA9b.js → workbenchSettings-YD0Ctbm_.js} +3 -3
  206. package/dist/renderer/entries/device-picker/index.html +28 -0
  207. package/dist/renderer/entries/host-sidebar-default/index.html +6 -5
  208. package/dist/renderer/entries/main/index.html +16 -17
  209. package/dist/renderer/entries/popover/index.html +16 -10
  210. package/dist/renderer/entries/project-create-dialog/index.html +12 -12
  211. package/dist/renderer/entries/settings/index.html +10 -10
  212. package/dist/renderer/entries/tooltip/index.html +5 -5
  213. package/dist/renderer/entries/update-dialog/index.html +10 -10
  214. package/dist/renderer/entries/workbench/index.html +49 -0
  215. package/dist/renderer/entries/workbench-settings/index.html +12 -11
  216. package/dist/service-host/host-env-update.cjs +23 -0
  217. package/dist/service-host/preload.cjs +24 -49
  218. package/dist/service-host/service-message-queue.cjs +71 -0
  219. package/dist/service-host/sync-impls/system-info.js +31 -9
  220. package/dist/shared/compile-mode-state.d.ts +73 -0
  221. package/dist/shared/compile-mode-state.js +100 -0
  222. package/dist/shared/compile-modes.d.ts +152 -0
  223. package/dist/shared/compile-modes.js +237 -0
  224. package/dist/shared/ipc-channels-overlays.d.ts +8 -2
  225. package/dist/shared/ipc-channels-overlays.js +19 -2
  226. package/dist/shared/ipc-channels.d.ts +5 -10
  227. package/dist/shared/ipc-channels.js +17 -14
  228. package/dist/shared/ipc-schemas.d.ts +76 -24
  229. package/dist/shared/ipc-schemas.js +55 -10
  230. package/dist/shared/project-window-types.d.ts +42 -0
  231. package/dist/shared/project-window-types.js +2 -0
  232. package/dist/shared/types.d.ts +43 -17
  233. package/dist/shared/view-ids.d.ts +1 -0
  234. package/dist/shared/view-ids.js +3 -1
  235. package/dist/simulator/assets/bridge-channels-B3JAmRfl.js +2 -0
  236. package/dist/simulator/assets/device-shell-ATEhHV2_.css +1 -0
  237. package/dist/simulator/assets/device-shell-pxnZZp10.js +431 -0
  238. package/dist/simulator/assets/simulator-Dwp7lnvu.js +10 -0
  239. package/dist/simulator/assets/simulator-mini-app-DFo7fhi5.js +2 -0
  240. package/dist/simulator/assets/simulator-ui-B2ddJB1R.js +2 -0
  241. package/dist/simulator/simulator.html +3 -3
  242. package/dist/simulator/temp-files.d.ts +6 -0
  243. package/dist/simulator/temp-files.js +46 -4
  244. package/dist/simulator/types.d.ts +7 -0
  245. package/dist/vscode-workbench/assets/__vite-browser-external-JIkWewFf.js +1 -0
  246. package/dist/vscode-workbench/assets/{dist-CMfmHflW.js → dist-CXG-u1VB.js} +3 -3
  247. package/dist/vscode-workbench/assets/{iconv-lite-umd-Bx8CgaZq.js → iconv-lite-umd-Dxx9Qyb4.js} +1 -1
  248. package/dist/vscode-workbench/assets/{index-CdG6YWhW.js → index-6VJMsaWj.js} +460 -460
  249. package/dist/vscode-workbench/assets/{jschardet-M0qgd2lN.js → jschardet-Ba3D16vt.js} +1 -1
  250. package/dist/vscode-workbench/index.html +1 -1
  251. package/package.json +11 -8
  252. package/dist/renderer/assets/button-D5Q2wkXq.js +0 -2
  253. package/dist/renderer/assets/constants-D7DfVqMp.js +0 -2
  254. package/dist/renderer/assets/constants-D8zsejFq.js +0 -2
  255. package/dist/renderer/assets/dialog-e1TecTOY.js +0 -46
  256. package/dist/renderer/assets/hostSidebarDefault-B3yLfy8j.js +0 -2
  257. package/dist/renderer/assets/index-CsPD68N_.js +0 -5
  258. package/dist/renderer/assets/ipc-channels-overlays-LsDzGAtV.js +0 -2
  259. package/dist/renderer/assets/jsx-runtime-2vXHouwr.css +0 -1
  260. package/dist/renderer/assets/popover-Dix5cm_b.js +0 -2
  261. package/dist/renderer/assets/project-api-k7Oq9iaq.js +0 -2
  262. package/dist/renderer/assets/select-acGb0AmJ.js +0 -2
  263. package/dist/renderer/assets/settings-CQrTMr43.js +0 -2
  264. package/dist/renderer/assets/settings-api-CrUQ9rYV.js +0 -2
  265. package/dist/renderer/assets/settings-tab-bar-Cw1kVIf2.js +0 -2
  266. package/dist/renderer/assets/types-CsEKtFyr.js +0 -2
  267. package/dist/renderer/assets/updateDialog-NsF8223A.js +0 -2
  268. package/dist/renderer/assets/view-api-CLn3rcQE.js +0 -2
  269. package/dist/simulator/assets/bridge-channels-zhsumfky.js +0 -2
  270. package/dist/simulator/assets/device-shell-CmtM1QxP.js +0 -2
  271. package/dist/simulator/assets/device-shell-iFZo1igL.css +0 -1
  272. package/dist/simulator/assets/simulator-CIobn3Mh.js +0 -10
  273. package/dist/simulator/assets/simulator-mini-app-CRe6n9br.js +0 -2
  274. package/dist/simulator/assets/simulator-ui-C_cP602X.js +0 -2
  275. package/dist/vscode-workbench/assets/__vite-browser-external-Bc1vizTf.js +0 -1
@@ -0,0 +1,100 @@
1
+ /**
2
+ * In-memory compile-mode model: selection tracks a minted id, not an index
3
+ * into a list. Storage (`CompileModes`, WeChat's `condition.miniprogram`
4
+ * shape) stays index-based so `project.config.json` keeps round-tripping —
5
+ * `stateFromStored`/`storedFromState` are the only two places index
6
+ * arithmetic happens at all. Everywhere else (in particular
7
+ * `applyCompileModeCommand`) only ever compares/reassigns ids, so deleting or
8
+ * reordering entries can never select the wrong mode by shifting a stale
9
+ * index onto it.
10
+ */
11
+ import { NORMAL_COMPILE_INDEX, normalizeCompileModes, } from './compile-modes.js';
12
+ /** An empty model — no custom modes, 普通编译 selected. */
13
+ export function emptyCompileModeState() {
14
+ return { selectedId: null, entries: [] };
15
+ }
16
+ /**
17
+ * Build the in-memory state from whatever is on disk, minting a fresh id for
18
+ * each surviving entry in list order. Selection is carried across as the
19
+ * entry's identity (the freshly minted id), not the raw numeric `current` —
20
+ * `normalizeCompileModes` may have already remapped `current` when dropping
21
+ * a malformed earlier entry, so the id assigned here already points at the
22
+ * same data the stored `current` named.
23
+ */
24
+ export function stateFromStored(raw, mintId) {
25
+ const stored = normalizeCompileModes(raw);
26
+ const entries = stored.list.map((mode) => ({ id: mintId(), mode }));
27
+ const selectedId = stored.current >= 0 && stored.current < entries.length
28
+ ? entries[stored.current].id
29
+ : null;
30
+ return { selectedId, entries };
31
+ }
32
+ /** Project the in-memory state back into the on-disk index-based shape. */
33
+ export function storedFromState(state) {
34
+ const list = state.entries.map((entry) => entry.mode);
35
+ const current = state.selectedId === null
36
+ ? NORMAL_COMPILE_INDEX
37
+ : state.entries.findIndex((entry) => entry.id === state.selectedId);
38
+ return { current: current < 0 ? NORMAL_COMPILE_INDEX : current, list };
39
+ }
40
+ /** The selected entry's mode, or `null` for 普通编译 (including a ghost id). */
41
+ export function selectedMode(state) {
42
+ if (state.selectedId === null)
43
+ return null;
44
+ return state.entries.find((entry) => entry.id === state.selectedId)?.mode ?? null;
45
+ }
46
+ /**
47
+ * Interpret one command against the current state. `relaunch` reports
48
+ * whether the running configuration changed, so a caller only restarts the
49
+ * simulator when the selected mode itself moved. A command that names an id
50
+ * nothing matches is a no-op and returns the SAME state reference (not a
51
+ * copy) so a caller can cheaply tell "nothing changed" from "changed".
52
+ */
53
+ export function applyCompileModeCommand(state, command, mintId) {
54
+ switch (command.type) {
55
+ case 'select': {
56
+ if (command.id === null) {
57
+ return { state: { ...state, selectedId: null }, relaunch: true };
58
+ }
59
+ if (!state.entries.some((entry) => entry.id === command.id)) {
60
+ return { state, relaunch: false };
61
+ }
62
+ return { state: { ...state, selectedId: command.id }, relaunch: true };
63
+ }
64
+ case 'add': {
65
+ const entry = { id: mintId(), mode: command.mode };
66
+ return {
67
+ state: { selectedId: entry.id, entries: [...state.entries, entry] },
68
+ relaunch: true,
69
+ };
70
+ }
71
+ case 'update': {
72
+ const index = state.entries.findIndex((entry) => entry.id === command.id);
73
+ if (index < 0) {
74
+ const entry = { id: mintId(), mode: command.mode };
75
+ return {
76
+ state: { selectedId: entry.id, entries: [...state.entries, entry] },
77
+ relaunch: true,
78
+ };
79
+ }
80
+ const entries = [...state.entries];
81
+ entries[index] = { id: command.id, mode: command.mode };
82
+ return {
83
+ state: { ...state, entries },
84
+ relaunch: state.selectedId === command.id,
85
+ };
86
+ }
87
+ case 'remove': {
88
+ if (!state.entries.some((entry) => entry.id === command.id)) {
89
+ return { state, relaunch: false };
90
+ }
91
+ const entries = state.entries.filter((entry) => entry.id !== command.id);
92
+ const wasSelected = state.selectedId === command.id;
93
+ return {
94
+ state: { selectedId: wasSelected ? null : state.selectedId, entries },
95
+ relaunch: wasSelected,
96
+ };
97
+ }
98
+ }
99
+ }
100
+ //# sourceMappingURL=compile-mode-state.js.map
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Single source of truth for the compile-mode model: the named modes a
3
+ * project defines, which one is selected, and how that selection resolves
4
+ * into the launch parameters a compile runs with.
5
+ *
6
+ * The stored form (`CompileModes`) is WeChat DevTools' `condition.miniprogram`
7
+ * shape, so `project.config.json` round-trips between both tools. Everything
8
+ * here is pure — the storage side lives in main's `project-repository.ts`,
9
+ * the UI side in the compile-mode popover.
10
+ */
11
+ /**
12
+ * The launch parameters a compile actually runs with, after resolving the
13
+ * selected compile mode. Derived, never the stored form — see `CompileModes`.
14
+ */
15
+ export interface CompileConfig {
16
+ startPage: string;
17
+ scene: number;
18
+ queryParams: {
19
+ key: string;
20
+ value: string;
21
+ }[];
22
+ }
23
+ /**
24
+ * One named compile mode. Field names and shape mirror WeChat DevTools'
25
+ * `project.config.json` → `condition.miniprogram.list[]` entry so the same
26
+ * file round-trips between both tools; `query` is therefore the raw
27
+ * `k=v&k2=v2` string it stores, not parsed pairs.
28
+ *
29
+ * `launchMode` / `partialCompile` are WeChat's own fields. We neither read
30
+ * nor write them, but they ride along on every mode so saving from here
31
+ * never drops what the other tool put in the file.
32
+ */
33
+ export interface CompileMode {
34
+ name: string;
35
+ pathName: string;
36
+ query: string;
37
+ /** `null` means "unset" — the resolver falls back to `DEFAULT_SCENE`. */
38
+ scene: number | null;
39
+ launchMode?: unknown;
40
+ partialCompile?: unknown;
41
+ }
42
+ /**
43
+ * A project's compile modes plus which one is selected. This is the stored
44
+ * form; the effective `CompileConfig` is resolved from it
45
+ * (`resolveCompileConfig` below).
46
+ */
47
+ export interface CompileModes {
48
+ /** Index into `list`. `-1` (`NORMAL_COMPILE_INDEX`) selects 普通编译. */
49
+ current: number;
50
+ list: CompileMode[];
51
+ }
52
+ /**
53
+ * `CompileModes.current` value selecting 普通编译 — launch the app's own
54
+ * entry page with the default scene and no params. It is not an entry in
55
+ * `list`: 普通编译 is fixed and has nothing to edit, matching WeChat, where
56
+ * the same fixed item sits above the custom list at index -1.
57
+ */
58
+ export declare const NORMAL_COMPILE_INDEX = -1;
59
+ /**
60
+ * Stand-in for a custom mode the user never named. It must not read as
61
+ * 普通编译: a mode can legitimately have an empty name AND an empty
62
+ * `pathName` (its 启动页面 left on 默认为首页) while still carrying params or
63
+ * a scene, and calling that 普通编译 would tell the user they are running
64
+ * something they are not.
65
+ */
66
+ export declare const UNNAMED_MODE_LABEL = "\u672A\u547D\u540D\u6A21\u5F0F";
67
+ /**
68
+ * Parse a raw `k=v&k2=v2` query string into ordered pairs.
69
+ *
70
+ * Unlike `decodePageSpec` (which yields a `Record` and so silently collapses
71
+ * repeats), this preserves order and duplicate keys — the k/v editor shows
72
+ * exactly what the user typed into the raw field, including `a=1&a=2`.
73
+ * A bare segment with no `=` parses to an empty value.
74
+ */
75
+ export declare function parseQueryString(query: string): {
76
+ key: string;
77
+ value: string;
78
+ }[];
79
+ /**
80
+ * Serialize ordered pairs back into a raw query string. Rows with an empty
81
+ * key are dropped — the k/v editor keeps a blank row around while the user
82
+ * is still typing, and a blank row is not a parameter.
83
+ */
84
+ export declare function stringifyQueryParams(params: {
85
+ key: string;
86
+ value: string;
87
+ }[]): string;
88
+ /**
89
+ * Resolve the selected mode into the launch parameters. 普通编译 (and any
90
+ * out-of-range `current`, which a hand-edited config file can produce)
91
+ * resolves to an empty `startPage`; the caller substitutes the project's own
92
+ * entry page for it, since only the caller knows the project.
93
+ */
94
+ export declare function resolveCompileConfig(modes: CompileModes): CompileConfig;
95
+ /**
96
+ * The id-based model's counterpart to `resolveCompileConfig`: derives the
97
+ * launch parameters straight from a single already-selected mode (or the
98
+ * normal-compile default for `null`) without any index/list to consult.
99
+ */
100
+ export declare function compileConfigFromMode(mode: CompileMode | null): CompileConfig;
101
+ /**
102
+ * Text for the toolbar's compile-mode button: the selected mode's name,
103
+ * falling back to its start page when the user left the name blank, so an
104
+ * unnamed mode is still identifiable. Only `null` (nothing selected) may
105
+ * produce the 普通编译 label — see {@link UNNAMED_MODE_LABEL}.
106
+ */
107
+ export declare function compileModeLabel(mode: CompileMode | null): string;
108
+ /**
109
+ * Coerce whatever is on disk into a usable `CompileModes`. The source is a
110
+ * user-editable JSON file that another tool also writes, so every field is
111
+ * treated as untrusted: a malformed file degrades to 普通编译 rather than
112
+ * failing the project open.
113
+ */
114
+ export declare function normalizeCompileModes(raw: unknown): CompileModes;
115
+ /** An empty model — no custom modes, 普通编译 selected. */
116
+ export declare function emptyCompileModes(): CompileModes;
117
+ /**
118
+ * Build a mode out of resolved launch parameters. Used to migrate a legacy
119
+ * single compile config into the list, and by the popover when the user
120
+ * turns the simulator's current page into a mode.
121
+ */
122
+ export declare function compileConfigToMode(config: CompileConfig, name: string): CompileMode;
123
+ /**
124
+ * Whether resolved launch parameters are exactly what 普通编译 already
125
+ * launches, and so carry nothing worth surfacing as a named mode. An empty
126
+ * `startPage` means "the app's own entry page", which is what 普通编译 is;
127
+ * `entryPagePath` lets a caller that knows the project also recognize a config
128
+ * that names that page outright.
129
+ */
130
+ export declare function isNormalCompile(config: CompileConfig, entryPagePath: string): boolean;
131
+ /**
132
+ * Project a single legacy compile config into the mode list, as one unnamed
133
+ * selected mode — unless it asks for nothing 普通编译 can't already do, in
134
+ * which case the list stays empty rather than gaining a mode that says the
135
+ * same thing as the fixed entry above it.
136
+ *
137
+ * Both places that meet the older single-config form go through here: the
138
+ * project repository migrating `dimina-projects.json`, and the workspace
139
+ * adapter reading a host that only implements `getCompileConfig`. Callers that
140
+ * can resolve the project's entry page pass it so a config naming that page
141
+ * counts as 普通编译 too.
142
+ */
143
+ export declare function compileConfigToModes(config: CompileConfig, entryPagePath?: string): CompileModes;
144
+ /**
145
+ * Build a mode from a `pagePath?k=v&…` route string — the format
146
+ * `getCurrentPageRoute` reports for the simulator's visible page, which is
147
+ * what "以当前页面新建编译模式" starts from. Scene is left unset so the new
148
+ * mode launches with the default rather than inheriting whatever scene the
149
+ * running session happened to use.
150
+ */
151
+ export declare function routeToMode(route: string, name: string): CompileMode;
152
+ //# sourceMappingURL=compile-modes.d.ts.map
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Single source of truth for the compile-mode model: the named modes a
3
+ * project defines, which one is selected, and how that selection resolves
4
+ * into the launch parameters a compile runs with.
5
+ *
6
+ * The stored form (`CompileModes`) is WeChat DevTools' `condition.miniprogram`
7
+ * shape, so `project.config.json` round-trips between both tools. Everything
8
+ * here is pure — the storage side lives in main's `project-repository.ts`,
9
+ * the UI side in the compile-mode popover.
10
+ */
11
+ import { DEFAULT_SCENE } from './constants.js';
12
+ /**
13
+ * `CompileModes.current` value selecting 普通编译 — launch the app's own
14
+ * entry page with the default scene and no params. It is not an entry in
15
+ * `list`: 普通编译 is fixed and has nothing to edit, matching WeChat, where
16
+ * the same fixed item sits above the custom list at index -1.
17
+ */
18
+ export const NORMAL_COMPILE_INDEX = -1;
19
+ /** Label shown when no custom mode is selected. */
20
+ const NORMAL_COMPILE_LABEL = '普通编译';
21
+ /**
22
+ * Stand-in for a custom mode the user never named. It must not read as
23
+ * 普通编译: a mode can legitimately have an empty name AND an empty
24
+ * `pathName` (its 启动页面 left on 默认为首页) while still carrying params or
25
+ * a scene, and calling that 普通编译 would tell the user they are running
26
+ * something they are not.
27
+ */
28
+ export const UNNAMED_MODE_LABEL = '未命名模式';
29
+ /**
30
+ * Parse a raw `k=v&k2=v2` query string into ordered pairs.
31
+ *
32
+ * Unlike `decodePageSpec` (which yields a `Record` and so silently collapses
33
+ * repeats), this preserves order and duplicate keys — the k/v editor shows
34
+ * exactly what the user typed into the raw field, including `a=1&a=2`.
35
+ * A bare segment with no `=` parses to an empty value.
36
+ */
37
+ export function parseQueryString(query) {
38
+ const pairs = [];
39
+ for (const segment of query.split('&')) {
40
+ if (!segment)
41
+ continue;
42
+ const eqIdx = segment.indexOf('=');
43
+ const rawKey = eqIdx >= 0 ? segment.slice(0, eqIdx) : segment;
44
+ const rawValue = eqIdx >= 0 ? segment.slice(eqIdx + 1) : '';
45
+ if (!rawKey)
46
+ continue;
47
+ pairs.push({ key: safeDecode(rawKey), value: safeDecode(rawValue) });
48
+ }
49
+ return pairs;
50
+ }
51
+ /**
52
+ * Serialize ordered pairs back into a raw query string. Rows with an empty
53
+ * key are dropped — the k/v editor keeps a blank row around while the user
54
+ * is still typing, and a blank row is not a parameter.
55
+ */
56
+ export function stringifyQueryParams(params) {
57
+ return params
58
+ .filter((p) => p.key)
59
+ .map((p) => `${encodeURIComponent(p.key)}=${encodeURIComponent(p.value)}`)
60
+ .join('&');
61
+ }
62
+ /**
63
+ * Resolve the selected mode into the launch parameters. 普通编译 (and any
64
+ * out-of-range `current`, which a hand-edited config file can produce)
65
+ * resolves to an empty `startPage`; the caller substitutes the project's own
66
+ * entry page for it, since only the caller knows the project.
67
+ */
68
+ export function resolveCompileConfig(modes) {
69
+ const { current, list } = modes;
70
+ const mode = Number.isInteger(current) && current >= 0 && current < list.length
71
+ ? list[current] ?? null
72
+ : null;
73
+ return compileConfigFromMode(mode);
74
+ }
75
+ /**
76
+ * The id-based model's counterpart to `resolveCompileConfig`: derives the
77
+ * launch parameters straight from a single already-selected mode (or the
78
+ * normal-compile default for `null`) without any index/list to consult.
79
+ */
80
+ export function compileConfigFromMode(mode) {
81
+ if (!mode) {
82
+ return { startPage: '', scene: DEFAULT_SCENE, queryParams: [] };
83
+ }
84
+ return {
85
+ startPage: mode.pathName,
86
+ scene: mode.scene ?? DEFAULT_SCENE,
87
+ queryParams: parseQueryString(mode.query),
88
+ };
89
+ }
90
+ /**
91
+ * Text for the toolbar's compile-mode button: the selected mode's name,
92
+ * falling back to its start page when the user left the name blank, so an
93
+ * unnamed mode is still identifiable. Only `null` (nothing selected) may
94
+ * produce the 普通编译 label — see {@link UNNAMED_MODE_LABEL}.
95
+ */
96
+ export function compileModeLabel(mode) {
97
+ if (!mode)
98
+ return NORMAL_COMPILE_LABEL;
99
+ return mode.name || mode.pathName || UNNAMED_MODE_LABEL;
100
+ }
101
+ /**
102
+ * Coerce whatever is on disk into a usable `CompileModes`. The source is a
103
+ * user-editable JSON file that another tool also writes, so every field is
104
+ * treated as untrusted: a malformed file degrades to 普通编译 rather than
105
+ * failing the project open.
106
+ */
107
+ export function normalizeCompileModes(raw) {
108
+ if (!isRecord(raw))
109
+ return emptyCompileModes();
110
+ const rawCurrent = Number.isInteger(raw.current)
111
+ ? raw.current
112
+ : NORMAL_COMPILE_INDEX;
113
+ // Dropping a malformed entry shifts every later entry down, so the selection
114
+ // is remapped while the list is built. Keeping the raw index would select a
115
+ // DIFFERENT mode than the file did — the file says 首页, the simulator
116
+ // launches 购物车. A selected entry that is itself dropped falls back to
117
+ // 普通编译.
118
+ const list = [];
119
+ let current = NORMAL_COMPILE_INDEX;
120
+ if (Array.isArray(raw.list)) {
121
+ for (const [index, item] of raw.list.entries()) {
122
+ const mode = normalizeCompileMode(item);
123
+ if (!mode)
124
+ continue;
125
+ if (index === rawCurrent)
126
+ current = list.length;
127
+ list.push(mode);
128
+ }
129
+ }
130
+ return { current, list };
131
+ }
132
+ /** An empty model — no custom modes, 普通编译 selected. */
133
+ export function emptyCompileModes() {
134
+ return { current: NORMAL_COMPILE_INDEX, list: [] };
135
+ }
136
+ /**
137
+ * Build a mode out of resolved launch parameters. Used to migrate a legacy
138
+ * single compile config into the list, and by the popover when the user
139
+ * turns the simulator's current page into a mode.
140
+ */
141
+ export function compileConfigToMode(config, name) {
142
+ return {
143
+ name,
144
+ pathName: config.startPage,
145
+ query: stringifyQueryParams(config.queryParams ?? []),
146
+ scene: config.scene,
147
+ };
148
+ }
149
+ /**
150
+ * Whether resolved launch parameters are exactly what 普通编译 already
151
+ * launches, and so carry nothing worth surfacing as a named mode. An empty
152
+ * `startPage` means "the app's own entry page", which is what 普通编译 is;
153
+ * `entryPagePath` lets a caller that knows the project also recognize a config
154
+ * that names that page outright.
155
+ */
156
+ export function isNormalCompile(config, entryPagePath) {
157
+ return (!config.startPage || config.startPage === entryPagePath)
158
+ && (config.scene ?? DEFAULT_SCENE) === DEFAULT_SCENE
159
+ && (config.queryParams?.length ?? 0) === 0;
160
+ }
161
+ /**
162
+ * Project a single legacy compile config into the mode list, as one unnamed
163
+ * selected mode — unless it asks for nothing 普通编译 can't already do, in
164
+ * which case the list stays empty rather than gaining a mode that says the
165
+ * same thing as the fixed entry above it.
166
+ *
167
+ * Both places that meet the older single-config form go through here: the
168
+ * project repository migrating `dimina-projects.json`, and the workspace
169
+ * adapter reading a host that only implements `getCompileConfig`. Callers that
170
+ * can resolve the project's entry page pass it so a config naming that page
171
+ * counts as 普通编译 too.
172
+ */
173
+ export function compileConfigToModes(config, entryPagePath = '') {
174
+ if (isNormalCompile(config, entryPagePath))
175
+ return emptyCompileModes();
176
+ return { current: 0, list: [compileConfigToMode(config, '')] };
177
+ }
178
+ /**
179
+ * Build a mode from a `pagePath?k=v&…` route string — the format
180
+ * `getCurrentPageRoute` reports for the simulator's visible page, which is
181
+ * what "以当前页面新建编译模式" starts from. Scene is left unset so the new
182
+ * mode launches with the default rather than inheriting whatever scene the
183
+ * running session happened to use.
184
+ */
185
+ export function routeToMode(route, name) {
186
+ const qIdx = route.indexOf('?');
187
+ return {
188
+ name,
189
+ pathName: qIdx >= 0 ? route.slice(0, qIdx) : route,
190
+ query: qIdx >= 0 ? route.slice(qIdx + 1) : '',
191
+ scene: null,
192
+ };
193
+ }
194
+ /**
195
+ * A mode needs a start page to mean anything, so an entry without a string
196
+ * `pathName` is dropped rather than kept as an unlaunchable row. Unknown
197
+ * fields WeChat writes are carried through untouched.
198
+ */
199
+ function normalizeCompileMode(raw) {
200
+ if (!isRecord(raw))
201
+ return null;
202
+ if (typeof raw.pathName !== 'string')
203
+ return null;
204
+ const scene = typeof raw.scene === 'number'
205
+ ? raw.scene
206
+ : typeof raw.scene === 'string' && raw.scene.trim() !== '' && Number.isFinite(Number(raw.scene))
207
+ ? Number(raw.scene)
208
+ : null;
209
+ const mode = {
210
+ name: typeof raw.name === 'string' ? raw.name : '',
211
+ pathName: raw.pathName,
212
+ query: typeof raw.query === 'string' ? raw.query : '',
213
+ scene,
214
+ };
215
+ if ('launchMode' in raw)
216
+ mode.launchMode = raw.launchMode;
217
+ if ('partialCompile' in raw)
218
+ mode.partialCompile = raw.partialCompile;
219
+ return mode;
220
+ }
221
+ /**
222
+ * `decodeURIComponent` throws on a lone `%` — which a user editing the raw
223
+ * query field types on the way to `%20`. Keep the literal text instead of
224
+ * losing the whole field to an exception.
225
+ */
226
+ function safeDecode(value) {
227
+ try {
228
+ return decodeURIComponent(value);
229
+ }
230
+ catch {
231
+ return value;
232
+ }
233
+ }
234
+ function isRecord(value) {
235
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
236
+ }
237
+ //# sourceMappingURL=compile-modes.js.map
@@ -118,7 +118,7 @@ export interface ViewBounds {
118
118
  export declare const PopoverChannel: {
119
119
  readonly Show: "popover:show";
120
120
  readonly Hide: "popover:hide";
121
- readonly Relaunch: "popover:relaunch";
121
+ readonly Apply: "popover:apply";
122
122
  readonly Closed: "popover:closed";
123
123
  readonly Init: "popover:init";
124
124
  };
@@ -139,9 +139,15 @@ export declare const ProjectCreateChannel: {
139
139
  readonly Cancel: "projectCreate:cancel";
140
140
  readonly Submitted: "projectCreate:submitted";
141
141
  };
142
+ export declare const DevicePickerChannel: {
143
+ readonly Show: "devicePicker:show";
144
+ readonly Init: "devicePicker:init";
145
+ readonly Select: "devicePicker:select";
146
+ readonly Cancel: "devicePicker:cancel";
147
+ readonly Selected: "devicePicker:selected";
148
+ };
142
149
  export declare const SettingsChannel: {
143
150
  readonly SetVisible: "settings:setVisible";
144
- readonly ConfigChanged: "settings:configChanged";
145
151
  readonly ProjectSettingsChanged: "settings:projectSettingsChanged";
146
152
  readonly Init: "settings:init";
147
153
  };
@@ -125,7 +125,10 @@ export const ViewChannel = {
125
125
  export const PopoverChannel = {
126
126
  Show: 'popover:show',
127
127
  Hide: 'popover:hide',
128
- Relaunch: 'popover:relaunch',
128
+ // Popover → main → main-renderer: the edited compile modes, plus whether
129
+ // the change affects what is currently running (selecting a mode, or
130
+ // editing the selected one) and so needs a relaunch.
131
+ Apply: 'popover:apply',
129
132
  Closed: 'popover:closed',
130
133
  Init: 'popover:init',
131
134
  };
@@ -164,10 +167,24 @@ export const ProjectCreateChannel = {
164
167
  Cancel: 'projectCreate:cancel',
165
168
  Submitted: 'projectCreate:submitted',
166
169
  };
170
+ // ── Device picker ────────────────────────────────────────────────────────
171
+ //
172
+ // A top-tier overlay WebContentsView (VIEW_LAYER.dialog), for the same reason
173
+ // as the project-create dialog above: the simulator's own WebContentsView is
174
+ // mounted on top of the main renderer and overlaps the centred search panel,
175
+ // so a DOM-portaled dialog is cut in half by it. The toolbar keeps only the
176
+ // trigger button; it asks main to show this panel with the currently selected
177
+ // device, and main relays the picked device name back to the toolbar.
178
+ export const DevicePickerChannel = {
179
+ Show: 'devicePicker:show',
180
+ Init: 'devicePicker:init',
181
+ Select: 'devicePicker:select',
182
+ Cancel: 'devicePicker:cancel',
183
+ Selected: 'devicePicker:selected',
184
+ };
167
185
  // ── Embedded settings overlay ────────────────────────────────────────────
168
186
  export const SettingsChannel = {
169
187
  SetVisible: 'settings:setVisible',
170
- ConfigChanged: 'settings:configChanged',
171
188
  ProjectSettingsChanged: 'settings:projectSettingsChanged',
172
189
  Init: 'settings:init',
173
190
  };
@@ -13,16 +13,8 @@ export declare const SimulatorChannel: {
13
13
  readonly Console: "simulator:console";
14
14
  readonly CurrentPage: "simulator:current-page";
15
15
  };
16
- /** iPhone bezel cutout family driving the device-shell notch visual. */
17
- export type { NativeDeviceInfo, NotchType, SafeAreaInsets, } from '@dimina-kit/electron-runtime';
16
+ export type { DeviceOrientation, NativeDeviceInfo, SafeAreaInsets, } from '@dimina-kit/electron-runtime';
18
17
  export declare const ServiceHostChannel: {
19
- /**
20
- * NATIVE-HOST ONLY. Live-update the service-host window's host-env snapshot
21
- * (device metrics) so subsequent `wx.getSystemInfoSync()` reflects a device
22
- * change without a relaunch. The service-host preload mutates
23
- * `__diminaSpawnContext.hostEnvSnapshot` in place (see `service-host/preload.cjs`).
24
- */
25
- readonly HostEnvUpdate: "service-host:host-env:update";
26
18
  /**
27
19
  * NATIVE-HOST ONLY. Deliver an AppData-panel edit (`{bridgeId, data}`) into
28
20
  * the service-host window. The preload resolves the page instance via
@@ -99,6 +91,9 @@ export declare const ProjectChannel: {
99
91
  readonly GetPages: "project:getPages";
100
92
  readonly GetCompileConfig: "project:getCompileConfig";
101
93
  readonly SaveCompileConfig: "project:saveCompileConfig";
94
+ readonly GetCompileModeState: "project:getCompileModeState";
95
+ readonly CompileModesChanged: "project:compileModesChanged";
96
+ readonly CompileModesApplyFailed: "project:compileModesApplyFailed";
102
97
  readonly Status: "project:status";
103
98
  readonly CompileLog: "project:compileLog";
104
99
  readonly CaptureThumbnail: "project:captureThumbnail";
@@ -162,7 +157,7 @@ export declare const DialogChannel: {
162
157
  export declare const WindowChannel: {
163
158
  readonly NavigateBack: "window:navigateBack";
164
159
  readonly OpenProject: "window:openProject";
165
- readonly ScreenState: "window:screenState";
160
+ readonly OpenProjectWindow: "window:openProjectWindow";
166
161
  };
167
162
  export declare const AppChannel: {
168
163
  readonly GetBranding: "app:getBranding";
@@ -34,13 +34,6 @@ export const SimulatorChannel = {
34
34
  };
35
35
  // ── Service host (main → hidden service-host window) ─────────────────────
36
36
  export const ServiceHostChannel = {
37
- /**
38
- * NATIVE-HOST ONLY. Live-update the service-host window's host-env snapshot
39
- * (device metrics) so subsequent `wx.getSystemInfoSync()` reflects a device
40
- * change without a relaunch. The service-host preload mutates
41
- * `__diminaSpawnContext.hostEnvSnapshot` in place (see `service-host/preload.cjs`).
42
- */
43
- HostEnvUpdate: 'service-host:host-env:update',
44
37
  /**
45
38
  * NATIVE-HOST ONLY. Deliver an AppData-panel edit (`{bridgeId, data}`) into
46
39
  * the service-host window. The preload resolves the page instance via
@@ -138,6 +131,19 @@ export const ProjectChannel = {
138
131
  GetPages: 'project:getPages',
139
132
  GetCompileConfig: 'project:getCompileConfig',
140
133
  SaveCompileConfig: 'project:saveCompileConfig',
134
+ // Renderer → main invoke: the id-based in-memory snapshot for the
135
+ // currently open project's `CompileModeStore`. There is no
136
+ // `SaveCompileModes` counterpart any more — the store is main's alone to
137
+ // mutate, via `PopoverChannel.Apply`'s command.
138
+ GetCompileModeState: 'project:getCompileModeState',
139
+ // Main → renderer push: the open project's `CompileModeStore` advanced —
140
+ // via the popover, or any other command source. Carries the full
141
+ // `CompileModeChange` (revision, state, relaunch).
142
+ CompileModesChanged: 'project:compileModesChanged',
143
+ // Main → renderer push: an `applyCompileModeCommand` rejected (e.g. a
144
+ // failed persist). Carries `{ message }`; the renderer surfaces it as a
145
+ // compile-status error without touching `compileModes`.
146
+ CompileModesApplyFailed: 'project:compileModesApplyFailed',
141
147
  Status: 'project:status',
142
148
  // Main → renderer push of per-line dmcc compile logs (devkit `onLog`).
143
149
  // Dedicated channel: `project:status` keeps its one-event-per-payload
@@ -214,13 +220,10 @@ export const DialogChannel = {
214
220
  export const WindowChannel = {
215
221
  NavigateBack: 'window:navigateBack',
216
222
  OpenProject: 'window:openProject',
217
- // Renderer → main: the renderer's current top-level screen ('project' when
218
- // inside a project screen, 'list' on the project list / landing). The
219
- // renderer pushes this on every screen change, including the moment it enters
220
- // a project — BEFORE the open resolves — so a FAILED open (no session) still
221
- // leaves main's mirror = 'project'. The window-close decision reads it so
222
- // closing a stuck/failed project returns to the list instead of quitting.
223
- ScreenState: 'window:screenState',
223
+ // Renderer → main invoke: open `project` in its own standalone workbench
224
+ // window (`entries/workbench/`), replacing the old in-place `page: 'project'`
225
+ // switch inside the list window's React tree.
226
+ OpenProjectWindow: 'window:openProjectWindow',
224
227
  };
225
228
  // ── App ──────────────────────────────────────────────────────────────────
226
229
  export const AppChannel = {