@dimina-kit/devtools 0.4.0-dev.20260828161241 → 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 (277) 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/render-host/pageFrame.html +1 -1
  173. package/dist/render-host/preload.cjs +16 -4
  174. package/dist/renderer/assets/button-CB2MWjHY.js +2 -0
  175. package/dist/renderer/assets/constants-CkoGPQTS.js +2 -0
  176. package/dist/renderer/assets/constants-zQZ2-y21.js +2 -0
  177. package/dist/renderer/assets/{createLucideIcon-Bqi8hpdi.js → createLucideIcon-cZ9FlZZw.js} +2 -2
  178. package/dist/renderer/assets/devicePicker-H2eIO4e1.js +2 -0
  179. package/dist/renderer/assets/dialog-pHzEA8Vx.js +46 -0
  180. package/dist/renderer/assets/dist-B5HADirS.js +2 -0
  181. package/dist/renderer/assets/{dist-DKWdE1TK.js → dist-DIFlRMKe.js} +2 -2
  182. package/dist/renderer/assets/hostSidebarDefault-DRWh6OCt.js +2 -0
  183. package/dist/renderer/assets/index-CEL_XFge.js +2 -0
  184. package/dist/renderer/assets/{input-Ct3alvkq.js → input-CAObw95L.js} +2 -2
  185. package/dist/renderer/assets/ipc-channels-overlays-gIPUFnqc.js +2 -0
  186. package/dist/renderer/assets/jsx-runtime-DICEQH_0.css +1 -0
  187. package/dist/renderer/assets/{jsx-runtime-DGLHmmOq.js → jsx-runtime-DIw5wnYl.js} +1 -1
  188. package/dist/renderer/assets/plus-BQ9u5EbL.js +2 -0
  189. package/dist/renderer/assets/popover-Cw7G2Ctp.js +2 -0
  190. package/dist/renderer/assets/presets-DMZOb9ay.js +2 -0
  191. package/dist/renderer/assets/project-api-YTOr_Yvo.js +2 -0
  192. package/dist/renderer/assets/{projectCreateDialog-Bbjz75bP.js → projectCreateDialog-BmLqiYxn.js} +2 -2
  193. package/dist/renderer/assets/search-BMvuYF48.js +2 -0
  194. package/dist/renderer/assets/select-nFP95TxM.js +2 -0
  195. package/dist/renderer/assets/settings-CnpVfSWt.js +2 -0
  196. package/dist/renderer/assets/settings-api-Ccsf-Nsj.js +2 -0
  197. package/dist/renderer/assets/settings-tab-bar-CAzrv32m.js +2 -0
  198. package/dist/renderer/assets/smartphone-Bb2GdIKy.js +2 -0
  199. package/dist/renderer/assets/tabs-CPKN3Mmq.js +2 -0
  200. package/dist/renderer/assets/{tooltip-B_-_YVbw.js → tooltip-D6AxXRk5.js} +2 -2
  201. package/dist/renderer/assets/types-Bh0hA7El.js +2 -0
  202. package/dist/renderer/assets/updateDialog-CwndJ0Bl.js +2 -0
  203. package/dist/renderer/assets/{utils-kfQov6Pa.js → utils-sEB5OZEQ.js} +2 -2
  204. package/dist/renderer/assets/view-api-B-2zPBR5.js +2 -0
  205. package/dist/renderer/assets/view-ids-BfaDVV5P.js +2 -0
  206. package/dist/renderer/assets/workbench-BLJ0wKsg.js +5 -0
  207. package/dist/renderer/assets/{workbenchSettings-CV4LVA9b.js → workbenchSettings-YD0Ctbm_.js} +3 -3
  208. package/dist/renderer/entries/device-picker/index.html +28 -0
  209. package/dist/renderer/entries/host-sidebar-default/index.html +6 -5
  210. package/dist/renderer/entries/main/index.html +16 -17
  211. package/dist/renderer/entries/popover/index.html +16 -10
  212. package/dist/renderer/entries/project-create-dialog/index.html +12 -12
  213. package/dist/renderer/entries/settings/index.html +10 -10
  214. package/dist/renderer/entries/tooltip/index.html +5 -5
  215. package/dist/renderer/entries/update-dialog/index.html +10 -10
  216. package/dist/renderer/entries/workbench/index.html +49 -0
  217. package/dist/renderer/entries/workbench-settings/index.html +12 -11
  218. package/dist/service-host/host-env-update.cjs +23 -0
  219. package/dist/service-host/preload.cjs +24 -49
  220. package/dist/service-host/service-message-queue.cjs +71 -0
  221. package/dist/service-host/sync-impls/system-info.js +31 -9
  222. package/dist/shared/compile-mode-state.d.ts +73 -0
  223. package/dist/shared/compile-mode-state.js +100 -0
  224. package/dist/shared/compile-modes.d.ts +152 -0
  225. package/dist/shared/compile-modes.js +237 -0
  226. package/dist/shared/ipc-channels-overlays.d.ts +8 -2
  227. package/dist/shared/ipc-channels-overlays.js +19 -2
  228. package/dist/shared/ipc-channels.d.ts +5 -10
  229. package/dist/shared/ipc-channels.js +17 -14
  230. package/dist/shared/ipc-schemas.d.ts +76 -24
  231. package/dist/shared/ipc-schemas.js +55 -10
  232. package/dist/shared/project-window-types.d.ts +42 -0
  233. package/dist/shared/project-window-types.js +2 -0
  234. package/dist/shared/types.d.ts +43 -17
  235. package/dist/shared/view-ids.d.ts +1 -0
  236. package/dist/shared/view-ids.js +3 -1
  237. package/dist/simulator/assets/bridge-channels-B3JAmRfl.js +2 -0
  238. package/dist/simulator/assets/device-shell-ATEhHV2_.css +1 -0
  239. package/dist/simulator/assets/device-shell-pxnZZp10.js +431 -0
  240. package/dist/simulator/assets/simulator-Dwp7lnvu.js +10 -0
  241. package/dist/simulator/assets/simulator-mini-app-DFo7fhi5.js +2 -0
  242. package/dist/simulator/assets/simulator-ui-B2ddJB1R.js +2 -0
  243. package/dist/simulator/simulator.html +3 -3
  244. package/dist/simulator/temp-files.d.ts +6 -0
  245. package/dist/simulator/temp-files.js +46 -4
  246. package/dist/simulator/types.d.ts +7 -0
  247. package/dist/vscode-workbench/assets/__vite-browser-external-JIkWewFf.js +1 -0
  248. package/dist/vscode-workbench/assets/{dist-CMfmHflW.js → dist-CXG-u1VB.js} +3 -3
  249. package/dist/vscode-workbench/assets/{iconv-lite-umd-Bx8CgaZq.js → iconv-lite-umd-Dxx9Qyb4.js} +1 -1
  250. package/dist/vscode-workbench/assets/{index-CdG6YWhW.js → index-6VJMsaWj.js} +460 -460
  251. package/dist/vscode-workbench/assets/{jschardet-M0qgd2lN.js → jschardet-Ba3D16vt.js} +1 -1
  252. package/dist/vscode-workbench/index.html +1 -1
  253. package/package.json +11 -8
  254. package/dist/renderer/assets/button-D5Q2wkXq.js +0 -2
  255. package/dist/renderer/assets/constants-D7DfVqMp.js +0 -2
  256. package/dist/renderer/assets/constants-D8zsejFq.js +0 -2
  257. package/dist/renderer/assets/dialog-e1TecTOY.js +0 -46
  258. package/dist/renderer/assets/hostSidebarDefault-B3yLfy8j.js +0 -2
  259. package/dist/renderer/assets/index-CsPD68N_.js +0 -5
  260. package/dist/renderer/assets/ipc-channels-overlays-LsDzGAtV.js +0 -2
  261. package/dist/renderer/assets/jsx-runtime-2vXHouwr.css +0 -1
  262. package/dist/renderer/assets/popover-Dix5cm_b.js +0 -2
  263. package/dist/renderer/assets/project-api-k7Oq9iaq.js +0 -2
  264. package/dist/renderer/assets/select-acGb0AmJ.js +0 -2
  265. package/dist/renderer/assets/settings-CQrTMr43.js +0 -2
  266. package/dist/renderer/assets/settings-api-CrUQ9rYV.js +0 -2
  267. package/dist/renderer/assets/settings-tab-bar-Cw1kVIf2.js +0 -2
  268. package/dist/renderer/assets/types-CsEKtFyr.js +0 -2
  269. package/dist/renderer/assets/updateDialog-NsF8223A.js +0 -2
  270. package/dist/renderer/assets/view-api-CLn3rcQE.js +0 -2
  271. package/dist/simulator/assets/bridge-channels-zhsumfky.js +0 -2
  272. package/dist/simulator/assets/device-shell-CmtM1QxP.js +0 -2
  273. package/dist/simulator/assets/device-shell-iFZo1igL.css +0 -1
  274. package/dist/simulator/assets/simulator-CIobn3Mh.js +0 -10
  275. package/dist/simulator/assets/simulator-mini-app-CRe6n9br.js +0 -2
  276. package/dist/simulator/assets/simulator-ui-C_cP602X.js +0 -2
  277. package/dist/vscode-workbench/assets/__vite-browser-external-Bc1vizTf.js +0 -1
@@ -128,6 +128,23 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
128
128
  pushData: (view, data) => ctx.notify.updateAvailable(view, data),
129
129
  readyMode: 'manual',
130
130
  });
131
+ const devicePickerPanel = createOverlayPanel({
132
+ electron: { createWebContentsView: (opts) => new WebContentsView(opts) },
133
+ rendererDir: ctx.rendererDir,
134
+ entry: 'entries/device-picker/index.html',
135
+ webPreferences: {
136
+ nodeIntegration: false,
137
+ contextIsolation: true,
138
+ sandbox: false,
139
+ preload: mainPreloadPath,
140
+ },
141
+ hardenNavigation: (wc) => applyNavigationHardening(wc, ctx.rendererDir),
142
+ setDesired: overlayDesiredSetter(VIEW_ID.devicePicker, VIEW_LAYER.dialog),
143
+ registerView: (getView) => reconciler.registerView(VIEW_ID.devicePicker, { getView }),
144
+ destroyView: (view) => reconciler.destroyView(VIEW_ID.devicePicker, view),
145
+ pushData: (view, data) => ctx.notify.devicePickerInit(view, data),
146
+ readyMode: 'manual',
147
+ });
131
148
  let tooltipRequestId = 0;
132
149
  let activeTooltip = null;
133
150
  async function showSettings() {
@@ -183,6 +200,12 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
183
200
  function hideUpdateDialog() {
184
201
  updateDialogPanel.hide();
185
202
  }
203
+ function showDevicePicker(data) {
204
+ devicePickerPanel.show(data, fullWindowBounds());
205
+ }
206
+ function hideDevicePicker() {
207
+ devicePickerPanel.hide();
208
+ }
186
209
  function notifyUpdateDownloadProgress(percent) {
187
210
  const wc = updateDialogPanel.getWebContents();
188
211
  if (!wc)
@@ -195,6 +218,7 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
195
218
  tooltipPanel.markReady(webContentsId);
196
219
  projectCreateDialogPanel.markReady(webContentsId);
197
220
  updateDialogPanel.markReady(webContentsId);
221
+ devicePickerPanel.markReady(webContentsId);
198
222
  }
199
223
  function applyTooltipMeasurement(webContentsId, measurement) {
200
224
  const active = activeTooltip;
@@ -222,6 +246,9 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
222
246
  if (updateDialogPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.updateDialog)) {
223
247
  updateDialogPanel.reposition(fullWindowBounds());
224
248
  }
249
+ if (devicePickerPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.devicePicker)) {
250
+ devicePickerPanel.reposition(fullWindowBounds());
251
+ }
225
252
  }
226
253
  function applySettingsBoundsIfPresent() {
227
254
  // See reapplyPresentOverlays() above for why this swallows a rejection.
@@ -237,6 +264,7 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
237
264
  function destroyDialogs() {
238
265
  projectCreateDialogPanel.destroy();
239
266
  updateDialogPanel.destroy();
267
+ devicePickerPanel.destroy();
240
268
  }
241
269
  return {
242
270
  showSettings,
@@ -253,6 +281,8 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
253
281
  showUpdateDialog,
254
282
  hideUpdateDialog,
255
283
  notifyUpdateDownloadProgress,
284
+ showDevicePicker,
285
+ hideDevicePicker,
256
286
  reapplyPresentOverlays,
257
287
  applySettingsBoundsIfPresent,
258
288
  destroySettings,
@@ -263,6 +293,7 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
263
293
  getTooltipWebContentsId: () => tooltipPanel.getWebContentsId(),
264
294
  getProjectCreateDialogWebContentsId: () => projectCreateDialogPanel.getWebContentsId(),
265
295
  getUpdateDialogWebContentsId: () => updateDialogPanel.getWebContentsId(),
296
+ getDevicePickerWebContentsId: () => devicePickerPanel.getWebContentsId(),
266
297
  };
267
298
  }
268
299
  //# sourceMappingURL=overlay-panels-view.js.map
@@ -93,7 +93,7 @@ export interface ViewManagerContext {
93
93
  * panels) and shares a single injected placement reconciler; this file wires
94
94
  * them together and exposes their combined method surface.
95
95
  */
96
- export interface ViewManager extends Pick<OverlayPanelsView, 'showSettings' | 'hideSettings' | 'showPopover' | 'hidePopover' | 'prepareTooltip' | 'showTooltip' | 'hideTooltip' | 'markOverlayReady' | 'applyTooltipMeasurement' | 'showProjectCreateDialog' | 'hideProjectCreateDialog' | 'showUpdateDialog' | 'hideUpdateDialog' | 'notifyUpdateDownloadProgress' | 'getProjectCreateDialogWebContentsId' | 'getUpdateDialogWebContentsId'>, HostSidebarViewManagerMembers, HostDialogViewManagerMembers {
96
+ export interface ViewManager extends Pick<OverlayPanelsView, 'showSettings' | 'hideSettings' | 'showPopover' | 'hidePopover' | 'prepareTooltip' | 'showTooltip' | 'hideTooltip' | 'markOverlayReady' | 'applyTooltipMeasurement' | 'showProjectCreateDialog' | 'hideProjectCreateDialog' | 'showUpdateDialog' | 'hideUpdateDialog' | 'notifyUpdateDownloadProgress' | 'showDevicePicker' | 'hideDevicePicker' | 'getProjectCreateDialogWebContentsId' | 'getUpdateDialogWebContentsId' | 'getDevicePickerWebContentsId'>, HostSidebarViewManagerMembers, HostDialogViewManagerMembers {
97
97
  /**
98
98
  * NATIVE-HOST ONLY. Create the simulator itself as a top-level
99
99
  * WebContentsView (not a renderer `<webview>` guest) loading `simulatorUrl`,
@@ -100,8 +100,11 @@ export function createViewManager(ctx) {
100
100
  showUpdateDialog: overlayPanels.showUpdateDialog,
101
101
  hideUpdateDialog: overlayPanels.hideUpdateDialog,
102
102
  notifyUpdateDownloadProgress: overlayPanels.notifyUpdateDownloadProgress,
103
+ showDevicePicker: overlayPanels.showDevicePicker,
104
+ hideDevicePicker: overlayPanels.hideDevicePicker,
103
105
  getProjectCreateDialogWebContentsId: overlayPanels.getProjectCreateDialogWebContentsId,
104
106
  getUpdateDialogWebContentsId: overlayPanels.getUpdateDialogWebContentsId,
107
+ getDevicePickerWebContentsId: overlayPanels.getDevicePickerWebContentsId,
105
108
  repositionAll: () => {
106
109
  overlayPanels.reapplyPresentOverlays();
107
110
  hostDialog.reposition();
@@ -0,0 +1,36 @@
1
+ import type { WebContents } from 'electron';
2
+ import { type Disposable } from '@dimina-kit/electron-deck/main';
3
+ import type { IpcContextSource } from '../../utils/ipc-context-source.js';
4
+ import type { SenderPolicy } from '../../utils/ipc-registry.js';
5
+ /**
6
+ * What the router needs of a window context to place an incoming sender.
7
+ * Kept to these two predicates so the router stays independent of the rest of
8
+ * the context; the concrete context type is supplied by the caller.
9
+ */
10
+ export interface RoutableWindowContext {
11
+ /** Every sender this window accepts, app-shared trusted windows included. */
12
+ senderPolicy: SenderPolicy;
13
+ /** Only the senders this window structurally owns (see sender-policy.ts). */
14
+ ownsSender: SenderPolicy;
15
+ }
16
+ /** Registry of live window contexts, and the authority on which one owns a sender. */
17
+ export interface WindowContextRouter<T extends RoutableWindowContext = RoutableWindowContext> extends IpcContextSource<T> {
18
+ /** Register a window context; the returned Disposable unregisters it. */
19
+ register(ctx: T): Disposable;
20
+ /**
21
+ * The context owning `sender`, or null when no registered context claims it.
22
+ * A pure query: looking a sender up never changes which context is active.
23
+ */
24
+ resolve(sender: WebContents): T | null;
25
+ /**
26
+ * The context last marked active by `setActive`. With none marked — or after
27
+ * the marked one unregisters — it falls back to the first still-registered
28
+ * context, and null when none are.
29
+ */
30
+ active(): T | null;
31
+ /** Mark `ctx` active (on window focus). Ignored for unregistered contexts. */
32
+ setActive(ctx: T): void;
33
+ list(): T[];
34
+ }
35
+ export declare function createWindowContextRouter<T extends RoutableWindowContext = RoutableWindowContext>(): WindowContextRouter<T>;
36
+ //# sourceMappingURL=context-router.d.ts.map
@@ -0,0 +1,55 @@
1
+ import { toDisposable } from '@dimina-kit/electron-deck/main';
2
+ export function createWindowContextRouter() {
3
+ const contexts = [];
4
+ let activeCtx = null;
5
+ const first = () => contexts[0] ?? null;
6
+ return {
7
+ register(ctx) {
8
+ contexts.push(ctx);
9
+ activeCtx ??= ctx;
10
+ return toDisposable(() => {
11
+ const at = contexts.indexOf(ctx);
12
+ if (at === -1)
13
+ return;
14
+ contexts.splice(at, 1);
15
+ if (activeCtx === ctx)
16
+ activeCtx = first();
17
+ });
18
+ },
19
+ resolve(sender) {
20
+ // Two passes, because the two predicates answer different questions.
21
+ // `senderPolicy` also accepts host windows registered through
22
+ // `registerTrustedWindow`, whose id map is app-wide — every context says
23
+ // yes to such a sender, so a single-pass scan would hand it to whichever
24
+ // window happened to register first. Pass one therefore only accepts a
25
+ // context that OWNS the sender (its own renderer, settings window or
26
+ // overlay views), which is unique by construction. Pass two covers the
27
+ // accepted-but-unowned senders that are left: they belong to the app
28
+ // rather than to a window, so the active window answers them.
29
+ //
30
+ // Neither pass moves "active": window focus is what decides which window
31
+ // an app-wide sender belongs to, and a background window handling its own
32
+ // IPC must not steal that answer from the focused one.
33
+ for (const ctx of contexts) {
34
+ if (ctx.ownsSender(sender))
35
+ return ctx;
36
+ }
37
+ for (const ctx of contexts) {
38
+ if (ctx.senderPolicy(sender))
39
+ return activeCtx ?? first();
40
+ }
41
+ return null;
42
+ },
43
+ active() {
44
+ return activeCtx ?? first();
45
+ },
46
+ setActive(ctx) {
47
+ if (contexts.includes(ctx))
48
+ activeCtx = ctx;
49
+ },
50
+ list() {
51
+ return contexts.slice();
52
+ },
53
+ };
54
+ }
55
+ //# sourceMappingURL=context-router.js.map
@@ -0,0 +1,52 @@
1
+ /**
2
+ * The single http listener behind every project window's workbench bridge.
3
+ *
4
+ * Browser storage is keyed by ORIGIN: IndexedDB, OPFS, Cache Storage, service
5
+ * worker registrations, Web Locks and BroadcastChannel all live in a bucket
6
+ * named after scheme + host + PORT. A listener bound to port 0 gets a different
7
+ * port every time, so one http server per project window put every window on
8
+ * its own origin — the VS Code workspace- and global-scope mementos a window
9
+ * wrote (open editors, view state, explorer expansion) died with it, reopening
10
+ * the same project minted a fresh empty bucket, and each new port accumulated
11
+ * another service-worker registration and cache entry that nothing reclaimed.
12
+ *
13
+ * So the listener is shared by every window in the process and a window's
14
+ * bridge is addressed by an opaque path prefix (`/w/<token>/`) rather than by
15
+ * port: one origin for all workbenches, distinct `/__fs` + `/__project`
16
+ * routing per window. The prefix is routing, not a security boundary — pages
17
+ * on one origin can already reach each other's paths, which is the situation
18
+ * the app-wide server had before per-project windows existed.
19
+ *
20
+ * The listener also outlives the last window that used it, because closing
21
+ * every project and opening another one is an ordinary switch and must not
22
+ * move the origin. Only {@link closeAllCoiHosts} takes a listener down.
23
+ */
24
+ import http from 'node:http';
25
+ export interface CoiHostSession {
26
+ /**
27
+ * Answers one request for this window. `url` has already had the window's
28
+ * `/w/<token>` prefix stripped, so the handler sees the same pathnames it
29
+ * would on a server of its own.
30
+ */
31
+ handle: (req: http.IncomingMessage, res: http.ServerResponse, url: URL) => void;
32
+ }
33
+ export interface CoiHostRegistration {
34
+ /** Scheme + host + port of the shared listener, with no trailing slash. */
35
+ origin: string;
36
+ port: number;
37
+ /** The path segment that routes to this session. */
38
+ token: string;
39
+ /** Drops the route, closing the shared listener when the last one goes. */
40
+ release: () => Promise<void>;
41
+ }
42
+ /**
43
+ * Tear down every listener. For process shutdown and for test isolation — a
44
+ * window's own teardown never gets here, because the origin has to survive it.
45
+ */
46
+ export declare function closeAllCoiHosts(): Promise<void>;
47
+ export declare function registerCoiHostSession(opts: {
48
+ rootDir: string;
49
+ extensionsDir: string | null;
50
+ session: CoiHostSession;
51
+ }): Promise<CoiHostRegistration>;
52
+ //# sourceMappingURL=workbench-coi-host.d.ts.map
@@ -0,0 +1,227 @@
1
+ /**
2
+ * The single http listener behind every project window's workbench bridge.
3
+ *
4
+ * Browser storage is keyed by ORIGIN: IndexedDB, OPFS, Cache Storage, service
5
+ * worker registrations, Web Locks and BroadcastChannel all live in a bucket
6
+ * named after scheme + host + PORT. A listener bound to port 0 gets a different
7
+ * port every time, so one http server per project window put every window on
8
+ * its own origin — the VS Code workspace- and global-scope mementos a window
9
+ * wrote (open editors, view state, explorer expansion) died with it, reopening
10
+ * the same project minted a fresh empty bucket, and each new port accumulated
11
+ * another service-worker registration and cache entry that nothing reclaimed.
12
+ *
13
+ * So the listener is shared by every window in the process and a window's
14
+ * bridge is addressed by an opaque path prefix (`/w/<token>/`) rather than by
15
+ * port: one origin for all workbenches, distinct `/__fs` + `/__project`
16
+ * routing per window. The prefix is routing, not a security boundary — pages
17
+ * on one origin can already reach each other's paths, which is the situation
18
+ * the app-wide server had before per-project windows existed.
19
+ *
20
+ * The listener also outlives the last window that used it, because closing
21
+ * every project and opening another one is an ordinary switch and must not
22
+ * move the origin. Only {@link closeAllCoiHosts} takes a listener down.
23
+ */
24
+ import http from 'node:http';
25
+ import path from 'node:path';
26
+ import { randomUUID } from 'node:crypto';
27
+ import { serveStaticFile, setIsolationHeaders } from './workbench-coi-static.js';
28
+ import { createCoiServerShutdown } from './workbench-coi-shutdown.js';
29
+ /**
30
+ * Tear down every listener. For process shutdown and for test isolation — a
31
+ * window's own teardown never gets here, because the origin has to survive it.
32
+ */
33
+ export async function closeAllCoiHosts() {
34
+ if (closingAll)
35
+ return closingAll;
36
+ const pending = [...hosts.values()];
37
+ hosts.clear();
38
+ const run = (async () => {
39
+ await Promise.all(pending.map(async (p) => {
40
+ const host = await p.catch(() => null);
41
+ if (!host || host.closed)
42
+ return;
43
+ host.closed = true;
44
+ await host.shutdown.close(host.server);
45
+ }));
46
+ })();
47
+ closingAll = run;
48
+ try {
49
+ await run;
50
+ }
51
+ finally {
52
+ if (closingAll === run)
53
+ closingAll = null;
54
+ }
55
+ }
56
+ /**
57
+ * One host per bundle + extensions pair. Two hosts serving different bundles
58
+ * are genuinely different servers; every window of one app shares one entry.
59
+ */
60
+ const hosts = new Map();
61
+ /**
62
+ * In-flight {@link closeAllCoiHosts}. A registration that was already waiting
63
+ * on `createHost` when a global close began must not hand its window an origin
64
+ * that close is about to take away, so it waits here and starts a fresh host.
65
+ */
66
+ let closingAll = null;
67
+ const WINDOW_PREFIX = /^\/w\/([A-Za-z0-9-]+)(\/.*)?$/;
68
+ function notFound(res) {
69
+ res.writeHead(404);
70
+ res.end('Not Found');
71
+ }
72
+ function badRequest(res) {
73
+ res.writeHead(400);
74
+ res.end('Bad Request');
75
+ }
76
+ function serverError(res) {
77
+ res.writeHead(500);
78
+ res.end('Internal Server Error');
79
+ }
80
+ async function createHost(rootDir) {
81
+ const sessions = new Map();
82
+ const shutdown = createCoiServerShutdown();
83
+ const server = http.createServer((req, res) => {
84
+ setIsolationHeaders(res);
85
+ let url;
86
+ try {
87
+ url = new URL(req.url ?? '/', 'http://127.0.0.1');
88
+ }
89
+ catch {
90
+ // A malformed request line must not become an uncaught exception in the
91
+ // main process.
92
+ badRequest(res);
93
+ return;
94
+ }
95
+ const routed = WINDOW_PREFIX.exec(url.pathname);
96
+ if (routed) {
97
+ const session = sessions.get(routed[1]);
98
+ // A request for a window that has already been torn down. 404 rather
99
+ // than fall through to the bundle: the caller asked for one specific
100
+ // window's bridge, and answering with another window's data would be
101
+ // worse than not answering.
102
+ if (!session) {
103
+ notFound(res);
104
+ return;
105
+ }
106
+ // Strip the prefix by rewriting `pathname` on a copy. Re-parsing the
107
+ // remainder as a URL reference would read a leading `//` as an authority,
108
+ // so `/w/<token>//__project` would arrive as `/` on host `__project`.
109
+ const forwarded = new URL(url);
110
+ forwarded.pathname = routed[2] || '/';
111
+ try {
112
+ session.handle(req, res, forwarded);
113
+ }
114
+ catch (err) {
115
+ // One window's handler must not take the shared listener's process
116
+ // with it — an uncaught exception here would end every other project
117
+ // window too. A handler answers its own client errors (a malformed
118
+ // percent escape, say), so anything reaching this point is a defect in
119
+ // it: 500 rather than 400, and logged, because a silent 400 would read
120
+ // as the caller's fault and hide the bug for good.
121
+ console.error('[workbench-coi] session handler threw', err);
122
+ if (res.headersSent)
123
+ res.destroy();
124
+ else
125
+ serverError(res);
126
+ }
127
+ return;
128
+ }
129
+ // No window prefix. Every bridge endpoint has to know WHICH window asked,
130
+ // so answering one here would mean guessing a project — the ambiguity the
131
+ // prefix exists to remove. The bundle itself is project-independent and is
132
+ // still served, so an absolute asset URL inside it keeps working.
133
+ if (url.pathname.startsWith('/__')) {
134
+ notFound(res);
135
+ return;
136
+ }
137
+ let decoded;
138
+ try {
139
+ decoded = decodeURIComponent(url.pathname);
140
+ }
141
+ catch {
142
+ // A stray `%` in the path. Answering 400 keeps the listener alive; the
143
+ // throw would otherwise escape the request handler.
144
+ badRequest(res);
145
+ return;
146
+ }
147
+ shutdown.trackRequest(res);
148
+ serveStaticFile(res, rootDir, decoded);
149
+ });
150
+ await new Promise((resolve, reject) => {
151
+ server.once('error', reject);
152
+ server.listen(0, '127.0.0.1', () => {
153
+ server.off('error', reject);
154
+ resolve();
155
+ });
156
+ });
157
+ const addr = server.address();
158
+ const port = typeof addr === 'object' && addr ? addr.port : 0;
159
+ return {
160
+ server,
161
+ origin: `http://127.0.0.1:${port}`,
162
+ port,
163
+ rootDir,
164
+ sessions,
165
+ shutdown,
166
+ closed: false,
167
+ };
168
+ }
169
+ export async function registerCoiHostSession(opts) {
170
+ const rootDir = path.resolve(opts.rootDir);
171
+ // JSON, not a separator character: `('/a', '/b|/c')` and `('/a|/b', '/c')`
172
+ // are both legal path pairs and would otherwise collide onto one host, so two
173
+ // different bundles would serve each other's files.
174
+ const key = JSON.stringify([rootDir, opts.extensionsDir ?? null]);
175
+ // Loop rather than a single lookup: a release running concurrently can have
176
+ // marked the cached host closed without having removed it yet, and joining a
177
+ // closing server would hand back a dead origin.
178
+ for (;;) {
179
+ if (closingAll) {
180
+ await closingAll;
181
+ continue;
182
+ }
183
+ let pending = hosts.get(key);
184
+ if (!pending) {
185
+ pending = createHost(rootDir);
186
+ hosts.set(key, pending);
187
+ }
188
+ let host;
189
+ try {
190
+ host = await pending;
191
+ }
192
+ catch (err) {
193
+ if (hosts.get(key) === pending)
194
+ hosts.delete(key);
195
+ throw err;
196
+ }
197
+ // `closingAll` is re-checked because it can have started while this
198
+ // registration was awaiting `pending`: the host may still read as open and
199
+ // yet be one `await` away from losing its port.
200
+ if (host.closed || closingAll || hosts.get(key) !== pending) {
201
+ if (hosts.get(key) === pending)
202
+ hosts.delete(key);
203
+ continue;
204
+ }
205
+ const token = randomUUID();
206
+ host.sessions.set(token, opts.session);
207
+ let released = false;
208
+ return {
209
+ origin: host.origin,
210
+ port: host.port,
211
+ token,
212
+ release: async () => {
213
+ if (released)
214
+ return;
215
+ released = true;
216
+ host.sessions.delete(token);
217
+ // The listener deliberately stays up with no windows on it. Closing it
218
+ // would release the port, and the next window would bind a different
219
+ // one — a different origin, so the storage the closed window wrote
220
+ // would be unreachable. Closing the last project and opening another
221
+ // is the ordinary way to switch projects, so the origin has to hold
222
+ // for the life of the process, not just while a window is open.
223
+ },
224
+ };
225
+ }
226
+ }
227
+ //# sourceMappingURL=workbench-coi-host.js.map