@dimina-kit/devtools 0.4.0-dev.20260701083540 → 0.4.0-dev.20260702145840

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 (81) hide show
  1. package/dist/main/app/app.js +11 -0
  2. package/dist/main/app/max-listeners-diagnostic.d.ts +32 -0
  3. package/dist/main/app/max-listeners-diagnostic.js +63 -0
  4. package/dist/main/index.bundle.js +1657 -1158
  5. package/dist/main/ipc/bridge-router.d.ts +33 -4
  6. package/dist/main/ipc/bridge-router.js +200 -51
  7. package/dist/main/ipc/session-listener-bag.d.ts +41 -0
  8. package/dist/main/ipc/session-listener-bag.js +40 -0
  9. package/dist/main/ipc/simulator.js +5 -5
  10. package/dist/main/ipc/views.js +8 -19
  11. package/dist/main/services/automation/wait-active-page.d.ts +4 -2
  12. package/dist/main/services/elements-forward/index.js +19 -0
  13. package/dist/main/services/network-forward/index.js +13 -0
  14. package/dist/main/services/render-inspect/index.d.ts +9 -0
  15. package/dist/main/services/render-inspect/index.js +13 -1
  16. package/dist/main/services/simulator-storage/index.d.ts +9 -0
  17. package/dist/main/services/simulator-storage/index.js +26 -1
  18. package/dist/main/services/simulator-wxml/index.js +117 -11
  19. package/dist/main/services/views/apply-view-ops.d.ts +11 -0
  20. package/dist/main/services/views/apply-view-ops.js +22 -0
  21. package/dist/main/services/views/destroy-child-view.d.ts +9 -0
  22. package/dist/main/services/views/destroy-child-view.js +23 -0
  23. package/dist/main/services/views/host-toolbar-view.d.ts +21 -0
  24. package/dist/main/services/views/host-toolbar-view.js +249 -0
  25. package/dist/main/services/views/inject-when-ready.d.ts +41 -0
  26. package/dist/main/services/views/inject-when-ready.js +62 -0
  27. package/dist/main/services/views/native-simulator-devtools-host.d.ts +26 -0
  28. package/dist/main/services/views/native-simulator-devtools-host.js +484 -0
  29. package/dist/main/services/views/native-simulator-view.d.ts +28 -0
  30. package/dist/main/services/views/native-simulator-view.js +428 -0
  31. package/dist/main/services/views/overlay-panels-view.d.ts +29 -0
  32. package/dist/main/services/views/overlay-panels-view.js +150 -0
  33. package/dist/main/services/views/placement-reconciler.d.ts +73 -0
  34. package/dist/main/services/views/placement-reconciler.js +120 -0
  35. package/dist/main/services/views/placement-test-driver.d.ts +25 -0
  36. package/dist/main/services/views/placement-test-driver.js +48 -0
  37. package/dist/main/services/views/resolve-project-editor-target.d.ts +13 -0
  38. package/dist/main/services/views/resolve-project-editor-target.js +33 -0
  39. package/dist/main/services/views/view-manager.d.ts +28 -70
  40. package/dist/main/services/views/view-manager.js +66 -1514
  41. package/dist/main/services/views/workbench-view.d.ts +15 -0
  42. package/dist/main/services/views/workbench-view.js +170 -0
  43. package/dist/main/services/workbench-context.d.ts +10 -0
  44. package/dist/preload/windows/host-toolbar-runtime.cjs +6 -13
  45. package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
  46. package/dist/preload/windows/main.cjs +10 -1
  47. package/dist/preload/windows/main.cjs.map +2 -2
  48. package/dist/preload/windows/simulator.cjs +6 -3
  49. package/dist/preload/windows/simulator.cjs.map +2 -2
  50. package/dist/preload/windows/simulator.js +6 -3
  51. package/dist/render-host/render-inspect.js +35 -1
  52. package/dist/renderer/assets/index-ChF9V4r-.js +49 -0
  53. package/dist/renderer/assets/{input-DR7bfyQE.js → input-Cjk0wSEh.js} +2 -2
  54. package/dist/renderer/assets/ipc-transport-D5dKIti1.css +1 -0
  55. package/dist/renderer/assets/{ipc-transport-3Arg8jPC.js → ipc-transport-OZS-KmOW.js} +2 -2
  56. package/dist/renderer/assets/{popover-CPZX3MrT.js → popover-CQVvOe90.js} +2 -2
  57. package/dist/renderer/assets/{select-BxyPlVyJ.js → select-BQDXi5ih.js} +2 -2
  58. package/dist/renderer/assets/{settings-api-CtPPJF-F.js → settings-api-B6x2mhaD.js} +2 -2
  59. package/dist/renderer/assets/{settings-CG_OR03F.js → settings-tP3Px2KR.js} +2 -2
  60. package/dist/renderer/assets/{workbenchSettings-ClqCBGOa.js → workbenchSettings-Bim9ol9R.js} +2 -2
  61. package/dist/renderer/entries/main/index.html +6 -6
  62. package/dist/renderer/entries/popover/index.html +5 -5
  63. package/dist/renderer/entries/settings/index.html +5 -5
  64. package/dist/renderer/entries/workbench-settings/index.html +4 -4
  65. package/dist/service-host/sync-api-patch.js +33 -3
  66. package/dist/shared/bridge-channels.d.ts +17 -0
  67. package/dist/shared/bridge-channels.js +9 -0
  68. package/dist/shared/ipc-channels.d.ts +29 -14
  69. package/dist/shared/ipc-channels.js +16 -17
  70. package/dist/shared/ipc-schemas.d.ts +25 -17
  71. package/dist/shared/ipc-schemas.js +38 -22
  72. package/dist/shared/view-ids.d.ts +19 -0
  73. package/dist/shared/view-ids.js +25 -0
  74. package/dist/simulator/assets/{bridge-channels-BUQ5AbvJ.js → bridge-channels-zhsumfky.js} +2 -2
  75. package/dist/simulator/assets/{device-shell-CT3LRnTB.js → device-shell-CUl0ILfn.js} +2 -2
  76. package/dist/simulator/assets/{simulator-BizhGGE3.js → simulator-Dz8iGcgy.js} +5 -5
  77. package/dist/simulator/assets/{simulator-mini-app-BfNuDF3R.js → simulator-mini-app-Bt639XL_.js} +2 -2
  78. package/dist/simulator/simulator.html +2 -1
  79. package/package.json +4 -4
  80. package/dist/renderer/assets/index-HE9Xr9bQ.js +0 -49
  81. package/dist/renderer/assets/ipc-transport-Dt0jR7Ir.css +0 -1
@@ -26,13 +26,13 @@
26
26
  overflow: hidden;
27
27
  }
28
28
  </style>
29
- <script type="module" crossorigin src="../../assets/index-HE9Xr9bQ.js"></script>
30
- <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-3Arg8jPC.js">
31
- <link rel="modulepreload" crossorigin href="../../assets/input-DR7bfyQE.js">
32
- <link rel="modulepreload" crossorigin href="../../assets/select-BxyPlVyJ.js">
33
- <link rel="modulepreload" crossorigin href="../../assets/settings-api-CtPPJF-F.js">
29
+ <script type="module" crossorigin src="../../assets/index-ChF9V4r-.js"></script>
30
+ <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-OZS-KmOW.js">
31
+ <link rel="modulepreload" crossorigin href="../../assets/input-Cjk0wSEh.js">
32
+ <link rel="modulepreload" crossorigin href="../../assets/select-BQDXi5ih.js">
33
+ <link rel="modulepreload" crossorigin href="../../assets/settings-api-B6x2mhaD.js">
34
34
  <link rel="modulepreload" crossorigin href="../../assets/constants-EAMiwL9_.js">
35
- <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-Dt0jR7Ir.css">
35
+ <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-D5dKIti1.css">
36
36
  </head>
37
37
  <body>
38
38
  <div id="root"></div>
@@ -8,12 +8,12 @@
8
8
  <style>
9
9
  html, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: transparent !important; }
10
10
  </style>
11
- <script type="module" crossorigin src="../../assets/popover-CPZX3MrT.js"></script>
12
- <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-3Arg8jPC.js">
13
- <link rel="modulepreload" crossorigin href="../../assets/input-DR7bfyQE.js">
14
- <link rel="modulepreload" crossorigin href="../../assets/select-BxyPlVyJ.js">
11
+ <script type="module" crossorigin src="../../assets/popover-CQVvOe90.js"></script>
12
+ <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-OZS-KmOW.js">
13
+ <link rel="modulepreload" crossorigin href="../../assets/input-Cjk0wSEh.js">
14
+ <link rel="modulepreload" crossorigin href="../../assets/select-BQDXi5ih.js">
15
15
  <link rel="modulepreload" crossorigin href="../../assets/constants-EAMiwL9_.js">
16
- <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-Dt0jR7Ir.css">
16
+ <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-D5dKIti1.css">
17
17
  </head>
18
18
  <body>
19
19
  <div id="root"></div>
@@ -11,11 +11,11 @@
11
11
  closes the overlay — mirrors the popover entry. */
12
12
  html, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: transparent !important; }
13
13
  </style>
14
- <script type="module" crossorigin src="../../assets/settings-CG_OR03F.js"></script>
15
- <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-3Arg8jPC.js">
16
- <link rel="modulepreload" crossorigin href="../../assets/input-DR7bfyQE.js">
17
- <link rel="modulepreload" crossorigin href="../../assets/settings-api-CtPPJF-F.js">
18
- <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-Dt0jR7Ir.css">
14
+ <script type="module" crossorigin src="../../assets/settings-tP3Px2KR.js"></script>
15
+ <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-OZS-KmOW.js">
16
+ <link rel="modulepreload" crossorigin href="../../assets/input-Cjk0wSEh.js">
17
+ <link rel="modulepreload" crossorigin href="../../assets/settings-api-B6x2mhaD.js">
18
+ <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-D5dKIti1.css">
19
19
  </head>
20
20
  <body>
21
21
  <div id="root"></div>
@@ -6,11 +6,11 @@
6
6
  <!-- See entries/main/index.html for CSP rationale. -->
7
7
  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: http: https:; font-src 'self' data:; media-src 'self' blob: http: https:; connect-src 'self' http: https: ws: wss:;" />
8
8
  <title>开发工具设置</title>
9
- <script type="module" crossorigin src="../../assets/workbenchSettings-ClqCBGOa.js"></script>
10
- <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-3Arg8jPC.js">
11
- <link rel="modulepreload" crossorigin href="../../assets/settings-api-CtPPJF-F.js">
9
+ <script type="module" crossorigin src="../../assets/workbenchSettings-Bim9ol9R.js"></script>
10
+ <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-OZS-KmOW.js">
11
+ <link rel="modulepreload" crossorigin href="../../assets/settings-api-B6x2mhaD.js">
12
12
  <link rel="modulepreload" crossorigin href="../../assets/constants-EAMiwL9_.js">
13
- <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-Dt0jR7Ir.css">
13
+ <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-D5dKIti1.css">
14
14
  </head>
15
15
  <body>
16
16
  <div id="root"></div>
@@ -2,13 +2,43 @@ import { getAccountInfoSync, getSystemInfoSync } from './sync-impls/system-info.
2
2
  import { clearStorageSync, getStorageInfoSync, getStorageSync, removeStorageSync, setStorageSync, } from './sync-impls/storage.js';
3
3
  import { getMenuButtonBoundingClientRect } from './sync-impls/menu-button.js';
4
4
  const spawnContext = (globalThis.__diminaSpawnContext ?? {});
5
+ /**
6
+ * Notify main that a SYNC storage API just mutated the service-host store, so the
7
+ * Storage panel updates live. Sync APIs write `localStorage` directly here and
8
+ * never round-trip through main (the async path already does), so without this
9
+ * the panel would only reflect sync writes on a manual reload. Best-effort: no
10
+ * bridge (pool-warming stub, or non-native runtime) → silently skip.
11
+ */
12
+ function notifyStorageChange(change) {
13
+ const bridge = globalThis.DiminaServiceBridge;
14
+ if (!bridge || typeof bridge.invoke !== 'function')
15
+ return;
16
+ bridge.invoke({ type: 'storageChanged', target: 'container', body: change });
17
+ }
18
+ /** Full storage key with the active appId namespace prefix (matches sync-impls). */
19
+ function fullKey(key) {
20
+ return `${spawnContext.appId ?? ''}_${key}`;
21
+ }
22
+ /** localStorage string form of a wx storage value (matches sync-impls/storage.ts). */
23
+ function encode(data) {
24
+ return typeof data === 'object' ? JSON.stringify(data) : String(data);
25
+ }
5
26
  function patchNamespace(ns) {
6
27
  if (!ns)
7
28
  return;
8
29
  ns.getStorageSync = (key) => getStorageSync.call(spawnContext, { key }).data ?? '';
9
- ns.setStorageSync = (key, data) => setStorageSync.call(spawnContext, { key, data });
10
- ns.removeStorageSync = (key) => removeStorageSync.call(spawnContext, { key });
11
- ns.clearStorageSync = () => clearStorageSync.call(spawnContext);
30
+ ns.setStorageSync = (key, data) => {
31
+ setStorageSync.call(spawnContext, { key, data });
32
+ notifyStorageChange({ op: 'set', key: fullKey(key), value: encode(data) });
33
+ };
34
+ ns.removeStorageSync = (key) => {
35
+ removeStorageSync.call(spawnContext, { key });
36
+ notifyStorageChange({ op: 'remove', key: fullKey(key) });
37
+ };
38
+ ns.clearStorageSync = () => {
39
+ clearStorageSync.call(spawnContext);
40
+ notifyStorageChange({ op: 'clear' });
41
+ };
12
42
  ns.getStorageInfoSync = () => getStorageInfoSync.call(spawnContext);
13
43
  ns.getSystemInfoSync = () => getSystemInfoSync.call(spawnContext);
14
44
  ns.getAccountInfoSync = () => getAccountInfoSync.call(spawnContext);
@@ -50,7 +50,24 @@ export declare const SIMULATOR_EVENTS: {
50
50
  * synchronously at preload bridge-install); this event covers live changes.
51
51
  */
52
52
  readonly DEVICE_CHANGE: "simulator:device-change";
53
+ /**
54
+ * main → simulator: a watcher rebuild finished; boot a NEW app session for
55
+ * the carried url ({@link RelaunchPayload}) IN PLACE, keeping the live
56
+ * DeviceShell painted, and swap once the new session's root page reports
57
+ * DOM_READY (ready-then-swap soft reload). Main sends this only when the
58
+ * shell is live+ready; otherwise the renderer falls back to the hard
59
+ * attachNativeSimulator rebuild.
60
+ */
61
+ readonly RELAUNCH: "simulator:relaunch";
53
62
  };
63
+ /**
64
+ * `simulator:relaunch` payload. `url` is a full simulator URL (same format as
65
+ * the simulator page's own location / AttachNative), carrying the appId and
66
+ * the page route the new session must boot at.
67
+ */
68
+ export interface RelaunchPayload {
69
+ url: string;
70
+ }
54
71
  export declare const CHANNELS: {
55
72
  readonly SPAWN: "dmb:spawn";
56
73
  readonly DISPOSE: "dmb:dispose";
@@ -49,6 +49,15 @@ export const SIMULATOR_EVENTS = {
49
49
  * synchronously at preload bridge-install); this event covers live changes.
50
50
  */
51
51
  DEVICE_CHANGE: 'simulator:device-change',
52
+ /**
53
+ * main → simulator: a watcher rebuild finished; boot a NEW app session for
54
+ * the carried url ({@link RelaunchPayload}) IN PLACE, keeping the live
55
+ * DeviceShell painted, and swap once the new session's root page reports
56
+ * DOM_READY (ready-then-swap soft reload). Main sends this only when the
57
+ * shell is live+ready; otherwise the renderer falls back to the hard
58
+ * attachNativeSimulator rebuild.
59
+ */
60
+ RELAUNCH: 'simulator:relaunch',
52
61
  };
53
62
  export const CHANNELS = BRIDGE_CHANNELS;
54
63
  /**
@@ -7,8 +7,8 @@
7
7
  */
8
8
  export declare const SimulatorChannel: {
9
9
  readonly AttachNative: "simulator:attach-native";
10
- readonly SetNativeBounds: "simulator:set-native-bounds";
11
10
  readonly SetDeviceInfo: "simulator:set-device-info";
11
+ readonly SoftReload: "simulator:soft-reload";
12
12
  readonly Detach: "simulator:detach";
13
13
  readonly Console: "simulator:console";
14
14
  readonly CurrentPage: "simulator:current-page";
@@ -92,6 +92,27 @@ export type StorageWriteResult = {
92
92
  ok: false;
93
93
  error: string;
94
94
  };
95
+ /**
96
+ * A storage mutation reported by the service-host's SYNC wx storage APIs
97
+ * (`setStorageSync`/`removeStorageSync`/`clearStorageSync`). Those run inside the
98
+ * service-host window and write `localStorage` directly, so — unlike the async
99
+ * path (`runtimeInvoke`) and the panel's own writes — they never pass through
100
+ * main and would otherwise leave the Storage panel stale until a manual reload.
101
+ * The service-host posts this over `DiminaServiceBridge` as a `storageChanged`
102
+ * container message; bridge-router hands it to `onServiceStorageChanged`, which
103
+ * pushes the matching `StorageEvent` to the panel. `key` carries the full
104
+ * `${appId}_` prefix (same wire shape as the CDP / async paths).
105
+ */
106
+ export type SyncStorageChange = {
107
+ op: 'set';
108
+ key: string;
109
+ value: string;
110
+ } | {
111
+ op: 'remove';
112
+ key: string;
113
+ } | {
114
+ op: 'clear';
115
+ };
95
116
  export declare const SimulatorElementChannel: {
96
117
  readonly Inspect: "simulator:element:inspect";
97
118
  readonly Clear: "simulator:element:clear";
@@ -99,6 +120,7 @@ export declare const SimulatorElementChannel: {
99
120
  export declare const SimulatorWxmlChannel: {
100
121
  readonly GetSnapshot: "simulator:wxml:snapshot";
101
122
  readonly Event: "simulator:wxml:event";
123
+ readonly SetActive: "simulator:wxml:setActive";
102
124
  };
103
125
  export declare const SimulatorAppDataChannel: {
104
126
  readonly GetSnapshot: "simulator:appdata:snapshot";
@@ -192,14 +214,6 @@ export declare const DialogChannel: {
192
214
  readonly OpenDirectory: "dialog:openDirectory";
193
215
  };
194
216
  export declare const ViewChannel: {
195
- /** Update the simulator DevTools view's bounds (or hide if w/h = 0). */
196
- readonly SimulatorDevtoolsBounds: "view:simulator:devtools-bounds";
197
- /**
198
- * Host-controllable toolbar WebContentsView (sits ABOVE the devtools built-in
199
- * header). Forward anchor: the main renderer reports the toolbar placeholder's
200
- * bounds (or w/h=0 to hide). invoke.
201
- */
202
- readonly HostToolbarBounds: "view:host-toolbar:bounds";
203
217
  /**
204
218
  * Reverse size-advertiser: the host-toolbar WCV's OWN renderer advertises its
205
219
  * intrinsic content height so main reserves exactly that much. Payload
@@ -232,12 +246,13 @@ export declare const ViewChannel: {
232
246
  */
233
247
  readonly HostToolbarGetHeight: "view:host-toolbar:get-height";
234
248
  /**
235
- * Update the embedded workbench editor view's bounds (or hide if w/h=0).
236
- * Forward anchor mirroring `SimulatorDevtoolsBounds`: the main renderer
237
- * measures the 'editor' dock slot's placeholder rect and publishes it so
238
- * main overlays the workbench WebContentsView precisely.
249
+ * Renderer main: the window-level placement snapshot (one monotonic epoch
250
+ * per commit tick, one generation per renderer lifetime) that drives the view
251
+ * reconciler. The single source of truth for every managed native view's
252
+ * bounds/visibility/z-order supersedes the per-view bounds channels above.
253
+ * invoke.
239
254
  */
240
- readonly WorkbenchBounds: "view:workbench-bounds";
255
+ readonly PlacementSnapshot: "view:placement-snapshot";
241
256
  };
242
257
  export interface ViewBounds {
243
258
  x: number;
@@ -10,15 +10,18 @@ export const SimulatorChannel = {
10
10
  // Ask main to create the simulator as a top-level WebContentsView (so nested
11
11
  // render-host <webview>s can attach). Native-host is the sole runtime.
12
12
  AttachNative: 'simulator:attach-native',
13
- // Renderer reports the device-bezel inner-screen rect (CSS px from content
14
- // top-left) + zoom so main can overlay the simulator WCV on it.
15
- SetNativeBounds: 'simulator:set-native-bounds',
16
13
  // Renderer pushes the selected device's LOGICAL metrics (screen size,
17
14
  // pixelRatio, statusBarHeight, …) when the device dropdown changes. Main
18
15
  // maps it to a HostEnvSnapshot and live-updates the running service-host
19
16
  // window — the authoritative `wx.getSystemInfoSync()` source — so the
20
17
  // mini-app sees the selected device without a relaunch.
21
18
  SetDeviceInfo: 'simulator:set-device-info',
19
+ // Ask main to soft-reload the LIVE simulator WCV after a watcher rebuild:
20
+ // main forwards a SIMULATOR_EVENTS.RELAUNCH into the shell (which boots a
21
+ // new app session and swaps when ready) instead of destroying the view.
22
+ // Resolves false when there is no live+ready shell — the renderer then falls
23
+ // back to the hard AttachNative rebuild.
24
+ SoftReload: 'simulator:soft-reload',
22
25
  Detach: 'simulator:detach',
23
26
  Console: 'simulator:console',
24
27
  // Main → renderer push of the visible top-of-stack page route whenever the
@@ -84,6 +87,10 @@ export const SimulatorElementChannel = {
84
87
  export const SimulatorWxmlChannel = {
85
88
  GetSnapshot: 'simulator:wxml:snapshot',
86
89
  Event: 'simulator:wxml:event',
90
+ // renderer→main: whether the WXML panel is currently visible/active. Main
91
+ // only installs the render-guest DOM MutationObserver + pushes live tree
92
+ // updates while active, so an unseen panel never drives a full Vue-tree walk.
93
+ SetActive: 'simulator:wxml:setActive',
87
94
  };
88
95
  // ── AppData (native-host: main taps the service→render setData stream in
89
96
  // bridge-router and pushes the cumulative snapshot here — the service logic runs
@@ -187,14 +194,6 @@ export const DialogChannel = {
187
194
  // pixels relative to the window's content area (origin = top-left,
188
195
  // not including the OS chrome).
189
196
  export const ViewChannel = {
190
- /** Update the simulator DevTools view's bounds (or hide if w/h = 0). */
191
- SimulatorDevtoolsBounds: 'view:simulator:devtools-bounds',
192
- /**
193
- * Host-controllable toolbar WebContentsView (sits ABOVE the devtools built-in
194
- * header). Forward anchor: the main renderer reports the toolbar placeholder's
195
- * bounds (or w/h=0 to hide). invoke.
196
- */
197
- HostToolbarBounds: 'view:host-toolbar:bounds',
198
197
  /**
199
198
  * Reverse size-advertiser: the host-toolbar WCV's OWN renderer advertises its
200
199
  * intrinsic content height so main reserves exactly that much. Payload
@@ -227,12 +226,13 @@ export const ViewChannel = {
227
226
  */
228
227
  HostToolbarGetHeight: 'view:host-toolbar:get-height',
229
228
  /**
230
- * Update the embedded workbench editor view's bounds (or hide if w/h=0).
231
- * Forward anchor mirroring `SimulatorDevtoolsBounds`: the main renderer
232
- * measures the 'editor' dock slot's placeholder rect and publishes it so
233
- * main overlays the workbench WebContentsView precisely.
229
+ * Renderer main: the window-level placement snapshot (one monotonic epoch
230
+ * per commit tick, one generation per renderer lifetime) that drives the view
231
+ * reconciler. The single source of truth for every managed native view's
232
+ * bounds/visibility/z-order supersedes the per-view bounds channels above.
233
+ * invoke.
234
234
  */
235
- WorkbenchBounds: 'view:workbench-bounds',
235
+ PlacementSnapshot: 'view:placement-snapshot',
236
236
  };
237
237
  // ── Popover ──────────────────────────────────────────────────────────────
238
238
  export const PopoverChannel = {
@@ -282,4 +282,3 @@ export const UpdateChannel = {
282
282
  DownloadProgress: 'updates:downloadProgress',
283
283
  Available: 'updates:available',
284
284
  };
285
- //# sourceMappingURL=ipc-channels.js.map
@@ -32,19 +32,11 @@ export declare const PopoverShowSchema: z.ZodTuple<[z.ZodObject<{}, z.core.$loos
32
32
  */
33
33
  export declare const SimulatorAttachNativeSchema: z.ZodTuple<[z.ZodString, z.ZodNumber], null>;
34
34
  /**
35
- * simulator:set-native-bounds (native-host only) — the renderer-measured
36
- * device-bezel inner-screen rect (CSS px, from `getBoundingClientRect()`, may
37
- * be fractional/zero) plus the device zoom percent. Positioned 1:1 as the
38
- * simulator WCV overlay bounds. Coordinates are plain finite numbers (x/y may
39
- * be negative when scrolled off-screen); zoom is the ZOOM_OPTIONS percent.
35
+ * simulator:soft-reload (native-host only) — the rebuilt simulator URL to
36
+ * soft-reload the live shell at. Same http(s)-only constraint as AttachNative
37
+ * (the URL becomes the new app session's route inside the existing WCV).
40
38
  */
41
- export declare const SimulatorSetNativeBoundsSchema: z.ZodTuple<[z.ZodObject<{
42
- x: z.ZodNumber;
43
- y: z.ZodNumber;
44
- width: z.ZodNumber;
45
- height: z.ZodNumber;
46
- zoom: z.ZodNumber;
47
- }, z.core.$strip>], null>;
39
+ export declare const SimulatorSoftReloadSchema: z.ZodTuple<[z.ZodString], null>;
48
40
  /**
49
41
  * simulator:set-device-info (native-host only) — the selected device's logical
50
42
  * metrics, mapped by main into the service-host window's HostEnvSnapshot. Sizes
@@ -72,11 +64,27 @@ export declare const SimulatorSetDeviceInfoSchema: z.ZodTuple<[z.ZodObject<{
72
64
  left: z.ZodNumber;
73
65
  }, z.core.$strip>;
74
66
  }, z.core.$strip>], null>;
75
- export declare const ViewBoundsSchema: z.ZodTuple<[z.ZodObject<{
76
- x: z.ZodNumber;
77
- y: z.ZodNumber;
78
- width: z.ZodNumber;
79
- height: z.ZodNumber;
67
+ export declare const PlacementSnapshotSchema: z.ZodTuple<[z.ZodObject<{
68
+ generation: z.ZodNumber;
69
+ epoch: z.ZodNumber;
70
+ views: z.ZodArray<z.ZodObject<{
71
+ viewId: z.ZodString;
72
+ placement: z.ZodUnion<readonly [z.ZodObject<{
73
+ visible: z.ZodLiteral<true>;
74
+ bounds: z.ZodObject<{
75
+ x: z.ZodNumber;
76
+ y: z.ZodNumber;
77
+ width: z.ZodNumber;
78
+ height: z.ZodNumber;
79
+ }, z.core.$strip>;
80
+ }, z.core.$strip>, z.ZodObject<{
81
+ visible: z.ZodLiteral<false>;
82
+ }, z.core.$strip>]>;
83
+ layer: z.ZodNumber;
84
+ extra: z.ZodOptional<z.ZodObject<{
85
+ zoom: z.ZodOptional<z.ZodNumber>;
86
+ }, z.core.$strip>>;
87
+ }, z.core.$strip>>;
80
88
  }, z.core.$strip>], null>;
81
89
  /**
82
90
  * host-toolbar reverse size-advertiser payload — the toolbar WCV renderer
@@ -62,19 +62,13 @@ export const SimulatorAttachNativeSchema = z.tuple([
62
62
  SimWidth,
63
63
  ]);
64
64
  /**
65
- * simulator:set-native-bounds (native-host only) — the renderer-measured
66
- * device-bezel inner-screen rect (CSS px, from `getBoundingClientRect()`, may
67
- * be fractional/zero) plus the device zoom percent. Positioned 1:1 as the
68
- * simulator WCV overlay bounds. Coordinates are plain finite numbers (x/y may
69
- * be negative when scrolled off-screen); zoom is the ZOOM_OPTIONS percent.
65
+ * simulator:soft-reload (native-host only) — the rebuilt simulator URL to
66
+ * soft-reload the live shell at. Same http(s)-only constraint as AttachNative
67
+ * (the URL becomes the new app session's route inside the existing WCV).
70
68
  */
71
- export const SimulatorSetNativeBoundsSchema = z.tuple([
72
- z.object({
73
- x: z.number().finite(),
74
- y: z.number().finite(),
75
- width: z.number().finite(),
76
- height: z.number().finite(),
77
- zoom: z.number().finite().positive(),
69
+ export const SimulatorSoftReloadSchema = z.tuple([
70
+ z.string().url().refine((u) => u.startsWith('http://') || u.startsWith('https://'), {
71
+ message: 'simulator URL must be http(s)',
78
72
  }),
79
73
  ]);
80
74
  /**
@@ -102,19 +96,41 @@ export const SimulatorSetDeviceInfoSchema = z.tuple([
102
96
  }),
103
97
  }),
104
98
  ]);
99
+ // Non-negative bounded integer used by the reverse height-advertise payload.
100
+ const NonNegInt = z.number().int().min(0).max(100_000);
105
101
  /**
106
- * view:*:boundsrenderer-measured CSS pixel rectangle in window content
107
- * coordinates. Width/height = 0 is the canonical "overlay hidden" signal.
108
- * No upper bound is enforced (window can be very large); we only refuse
109
- * negative/NaN values that would break setBounds.
102
+ * view:placement-snapshotthe window-level desired-placement table driving
103
+ * the reconciler. `generation`/`epoch` are non-negative monotonic counters.
104
+ * Each view carries an opaque string id, a discriminated placement (visible +
105
+ * bounds, or hidden — bounds are plain finite numbers: x/y may be negative when
106
+ * scrolled off-screen, w/h may be 0 for a visible-but-empty view), a z-order
107
+ * layer, and optional host extras (the simulator's zoom).
110
108
  */
111
- const NonNegInt = z.number().int().min(0).max(100_000);
112
- export const ViewBoundsSchema = z.tuple([
109
+ const FiniteNum = z.number().finite();
110
+ const PlacementSchema = z.union([
111
+ z.object({
112
+ visible: z.literal(true),
113
+ bounds: z.object({
114
+ x: FiniteNum,
115
+ y: FiniteNum,
116
+ width: FiniteNum,
117
+ height: FiniteNum,
118
+ }),
119
+ }),
120
+ z.object({ visible: z.literal(false) }),
121
+ ]);
122
+ export const PlacementSnapshotSchema = z.tuple([
113
123
  z.object({
114
- x: NonNegInt,
115
- y: NonNegInt,
116
- width: NonNegInt,
117
- height: NonNegInt,
124
+ generation: z.number().int().min(0),
125
+ epoch: z.number().int().min(0),
126
+ views: z.array(z.object({
127
+ viewId: z.string().min(1).max(64),
128
+ placement: PlacementSchema,
129
+ layer: z.number().int(),
130
+ extra: z
131
+ .object({ zoom: z.number().finite().positive().optional() })
132
+ .optional(),
133
+ })).max(64),
118
134
  }),
119
135
  ]);
120
136
  /**
@@ -0,0 +1,19 @@
1
+ export declare const VIEW_ID: {
2
+ readonly simulator: "simulator";
3
+ readonly simulatorDevtools: "simulator-devtools";
4
+ readonly workbench: "workbench";
5
+ readonly hostToolbar: "host-toolbar";
6
+ readonly settings: "settings";
7
+ readonly popover: "popover";
8
+ };
9
+ export type DevtoolsViewId = (typeof VIEW_ID)[keyof typeof VIEW_ID];
10
+ export interface DevtoolsExtra {
11
+ zoom?: number;
12
+ }
13
+ export declare const VIEW_LAYER: {
14
+ readonly base: 0;
15
+ readonly hostToolbar: 5;
16
+ readonly settings: 10;
17
+ readonly popover: 20;
18
+ };
19
+ //# sourceMappingURL=view-ids.d.ts.map
@@ -0,0 +1,25 @@
1
+ // The devtools view set fed through the placement reconciler. The reconcile
2
+ // core (@dimina-kit/electron-deck/layout) is domain-neutral over opaque string
3
+ // ids and an Extra type param; these are devtools' concrete bindings. Lives in
4
+ // shared/ so both the main-process reconciler and the renderer's placement
5
+ // publisher import the same ids and layers.
6
+ export const VIEW_ID = {
7
+ simulator: 'simulator',
8
+ simulatorDevtools: 'simulator-devtools',
9
+ workbench: 'workbench',
10
+ hostToolbar: 'host-toolbar',
11
+ settings: 'settings',
12
+ popover: 'popover',
13
+ };
14
+ // z-order layers; larger paints on top. Base overlays share layer 0 (they never
15
+ // overlap each other — the simulator device WCV, the console/DevTools WCV, and
16
+ // the embedded workbench occupy disjoint dock regions). The host-toolbar strip
17
+ // sits above the base row; settings and popover are the top tier (settings below
18
+ // a simultaneously-open popover), replacing the imperative raiseTopOverlays.
19
+ export const VIEW_LAYER = {
20
+ base: 0,
21
+ hostToolbar: 5,
22
+ settings: 10,
23
+ popover: 20,
24
+ };
25
+ //# sourceMappingURL=view-ids.js.map
@@ -1,2 +1,2 @@
1
- var e={DOM_READY:`simulator:dom-ready`,NAV_BAR:`simulator:navigation-bar`,NAV_ACTION:`simulator:nav-action`,TAB_ACTION:`simulator:tab-action`,API_CALL:`simulator:api-call`,DEVICE_CHANGE:`simulator:device-change`};export{e as t};
2
- //# sourceMappingURL=bridge-channels-BUQ5AbvJ.js.map
1
+ var e={DOM_READY:`simulator:dom-ready`,NAV_BAR:`simulator:navigation-bar`,NAV_ACTION:`simulator:nav-action`,TAB_ACTION:`simulator:tab-action`,API_CALL:`simulator:api-call`,DEVICE_CHANGE:`simulator:device-change`,RELAUNCH:`simulator:relaunch`};export{e as t};
2
+ //# sourceMappingURL=bridge-channels-zhsumfky.js.map
@@ -1,2 +1,2 @@
1
- import{n as e,r as t,t as n}from"./jsx-runtime-CDK-o-S0.js";import{t as r}from"./bridge-channels-BUQ5AbvJ.js";var i=t(),a=new Set([`audioListen`]);function o(e){return a.has(e)}function s(e,t,n,r){let i=e.apiRegistry[t];if(!i)return r({ok:!1,errMsg:`${t}:fail no handler`}),Promise.resolve();let a=o(t)||(n&&typeof n==`object`&&!Array.isArray(n)?n.keep===!0:!1);return new Promise(o=>{let s=!1,c=e=>{if(s){a&&e.ok&&r({...e,keep:!0});return}s=!0,r(a&&e.ok?{...e,keep:!0}:e),o()},l=Symbol(`sim-cb-success`),u=Symbol(`sim-cb-fail`),d=Symbol(`sim-cb-complete`),f=!1,p=Object.create(e);p.createCallbackFunction=e=>{if(e!=null)return(e===l||e===u)&&(f=!0),(...n)=>{let r=n[0];e===l?c({ok:!0,result:r}):e===u?c({ok:!1,errMsg:r&&typeof r==`object`&&`errMsg`in r?String(r.errMsg):`${t}:fail`,result:r}):e===d&&!a&&c({ok:!0,result:r})}};let m=n&&typeof n==`object`&&!Array.isArray(n)?{...n}:{};m.success=l,m.fail=u,m.complete=d;try{let e=i.call(p,m);if(e&&typeof e.then==`function`){Promise.resolve(e).then(e=>c({ok:!0,result:e}),e=>{c({ok:!1,errMsg:`${t}:fail ${e instanceof Error?e.message:String(e)}`})});return}if(s)return;if(a){o();return}if(f){o();return}c({ok:!0,result:e})}catch(e){c({ok:!1,errMsg:`${t}:fail ${e instanceof Error?e.message:String(e)}`})}})}var c=n();function l({platform:e,statusBarHeight:t,textStyle:n}){let r=e===`ios`?87:95,i=t+(e===`ios`?4:6),a=e===`ios`?7:10;return(0,c.jsxs)(`div`,{className:`menu-capsule menu-capsule--${n}`,style:{width:r,height:32,top:i,right:a},"aria-hidden":`true`,children:[(0,c.jsxs)(`div`,{className:`menu-capsule__more`,children:[(0,c.jsx)(`span`,{}),(0,c.jsx)(`span`,{}),(0,c.jsx)(`span`,{})]}),(0,c.jsx)(`div`,{className:`menu-capsule__divider`}),(0,c.jsx)(`div`,{className:`menu-capsule__close`,children:(0,c.jsx)(`svg`,{viewBox:`0 0 16 16`,width:`12`,height:`12`,"aria-hidden":`true`,children:(0,c.jsx)(`path`,{d:`M4 4l8 8M12 4l-8 8`,stroke:`currentColor`,strokeWidth:`1.5`,fill:`none`,strokeLinecap:`round`})})})]})}var u={linear:`linear`,easeIn:`ease-in`,easeOut:`ease-out`,easeInOut:`ease-in-out`};function d({state:e,stackDepth:t,platform:n,statusBarHeight:r,navBarHeight:a,onBack:o,onHome:s}){let d=(0,i.useMemo)(()=>{if(!e.colorAnimation||e.colorAnimation.durationMs<=0)return;let t=u[e.colorAnimation.timingFunc]??`linear`;return`background-color ${e.colorAnimation.durationMs}ms ${t}, color ${e.colorAnimation.durationMs}ms ${t}`},[e.colorAnimation]),f=e.style===`custom`,p=t>1,m=!p&&e.homeButtonVisible,h=n===`ios`?`center`:`left`,g={backgroundColor:e.backgroundColor,color:e.textStyle===`white`?`#ffffff`:`#000000`,height:r+a,paddingTop:r,transition:d};return(0,c.jsxs)(`header`,{className:`nav-bar nav-bar--${n} nav-bar--${e.textStyle}${f?` nav-bar--custom`:``}`,style:g,"aria-hidden":f,children:[!f&&(0,c.jsxs)(`div`,{className:`nav-bar__row`,style:{height:a,justifyContent:h===`center`?`center`:`flex-start`},children:[(p||m)&&(0,c.jsxs)(`div`,{className:`nav-bar__leading`,children:[p&&(0,c.jsx)(`button`,{type:`button`,className:`nav-bar__back`,"aria-label":`Back`,onClick:o,children:(0,c.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`24`,height:`24`,"aria-hidden":`true`,children:(0,c.jsx)(`path`,{d:`M15 18l-6-6 6-6`,stroke:`currentColor`,strokeWidth:`2`,fill:`none`,strokeLinecap:`round`,strokeLinejoin:`round`})})}),m&&(0,c.jsx)(`button`,{type:`button`,className:`nav-bar__home`,"aria-label":`Home`,onClick:s,children:(0,c.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`22`,height:`22`,"aria-hidden":`true`,children:(0,c.jsx)(`path`,{d:`M3 12l9-9 9 9M5 10v10h14V10`,stroke:`currentColor`,strokeWidth:`2`,fill:`none`,strokeLinecap:`round`,strokeLinejoin:`round`})})})]}),(0,c.jsxs)(`div`,{className:`nav-bar__title nav-bar__title--${h}`,style:{color:e.textStyle===`white`?`#ffffff`:`#000000`},children:[e.loading&&(0,c.jsx)(`span`,{className:`nav-bar__spinner`,"aria-hidden":`true`}),(0,c.jsx)(`span`,{className:`nav-bar__title-text`,children:e.title})]})]}),(0,c.jsx)(l,{platform:n,statusBarHeight:r,textStyle:e.textStyle})]})}function f(e){return{title:e?.title??``,backgroundColor:e?.backgroundColor??`#000000`,textStyle:e?.textStyle??`white`,style:e?.style??`default`,loading:e?.loading??!1,homeButtonVisible:e?.homeButtonVisible??!1,colorAnimation:e?.colorAnimation}}function p(e){switch(e){case`notch`:return{width:164,height:30,top:0,bottomOnly:!0};case`dynamic-island`:return{width:124,height:36,top:11,bottomOnly:!1};default:return null}}function m({height:e,notchType:t,textStyle:n}){let r=p(t);return(0,c.jsxs)(`div`,{className:`device-statusbar`,style:{height:e,color:n===`black`?`#000000`:`#ffffff`},"aria-hidden":`true`,children:[(0,c.jsx)(`span`,{className:`device-statusbar__time`,children:`9:41`}),r&&(0,c.jsx)(`div`,{className:`device-statusbar__notch`,style:{width:r.width,height:r.height,top:r.top,borderRadius:r.bottomOnly?`0 0 ${Math.round(r.height*.6)}px ${Math.round(r.height*.6)}px`:`${r.height/2}px`}}),(0,c.jsxs)(`div`,{className:`device-statusbar__icons`,children:[(0,c.jsx)(`span`,{className:`device-statusbar__signal`}),(0,c.jsx)(`span`,{className:`device-statusbar__wifi`}),(0,c.jsx)(`span`,{className:`device-statusbar__battery`})]})]})}function h({state:e,currentPath:t,resourceBaseUrl:n,appId:r,onSwitch:i,bottomInset:a=0}){if(!e.config||!e.visible)return null;let{color:o,selectedColor:s,backgroundColor:l,borderStyle:u,list:d}=e.config,f=o||`#999999`,p=s||`#1890ff`;return(0,c.jsx)(`div`,{className:`dmb-tab-bar`,style:{backgroundColor:l||`#ffffff`,borderTopColor:u===`white`?`#ffffff`:`#e0e0e0`,paddingBottom:a},role:`tablist`,"aria-label":`TabBar`,children:d.map((a,o)=>{let s=g(a.pagePath),l=s===t,u=_(l?a.selectedIconPath??a.iconPath:a.iconPath,n,r),d=e.badges[o]??``,m=e.redDots[o]??!1;return(0,c.jsxs)(`button`,{type:`button`,className:`dmb-tab-bar__item${l?` is-selected`:``}`,role:`tab`,"aria-selected":l,onClick:()=>i(s),children:[u&&(0,c.jsx)(`span`,{className:`dmb-tab-bar__icon-slot`,children:(0,c.jsx)(`img`,{className:`dmb-tab-bar__icon`,src:u,alt:``,onError:e=>{e.currentTarget.style.display=`none`}})}),(0,c.jsx)(`span`,{className:`dmb-tab-bar__text`,style:{color:l?p:f},children:a.text||``}),d&&(0,c.jsx)(`span`,{className:`dmb-tab-bar__badge`,children:d}),!d&&m&&(0,c.jsx)(`span`,{className:`dmb-tab-bar__red-dot`})]},`${s}-${o}`)})})}function g(e){return e?e.replace(/^\/+/,``):``}function _(e,t,n){if(!e)return null;let r=e.trim();if(!r)return null;if(/^(?:data:|blob:|https?:|\/\/)/i.test(r))return r;if(!t)return null;let i=r.replace(/^\/+/,``).replace(/^\.\//,``);return i.startsWith(`${n}/`)?v(t,i):v(t,`${n}/main/${i}`)}function v(e,t){return`${e.endsWith(`/`)?e:`${e}/`}${t.replace(/^\/+/,``)}`}function y(){let[{toast:t,dialog:n},r]=(0,i.useState)(()=>e.getState());return(0,i.useEffect)(()=>e.subscribe(r),[]),(0,c.jsxs)(c.Fragment,{children:[t&&(0,c.jsx)(b,{toast:t}),n?.kind===`modal`&&(0,c.jsx)(S,{dialog:n}),n?.kind===`actionSheet`&&(0,c.jsx)(C,{dialog:n})]})}function b({toast:t}){(0,i.useEffect)(()=>{if(!Number.isFinite(t.duration))return;let n=window.setTimeout(()=>e.dismissToast(t),t.duration);return()=>window.clearTimeout(n)},[t]);let n=t.icon!==`none`||!!t.image;return(0,c.jsxs)(`div`,{className:`dmui-overlay`,"aria-live":`polite`,children:[t.mask&&(0,c.jsx)(`div`,{className:`dmui-mask dmui-mask--transparent`}),(0,c.jsxs)(`div`,{className:`dmui-toast${n?``:` dmui-toast--text`}`,role:`alert`,children:[t.image?(0,c.jsx)(`img`,{className:`dmui-toast__image`,src:t.image,alt:``}):(0,c.jsx)(x,{icon:t.icon}),t.title&&(0,c.jsx)(`div`,{className:`dmui-toast__title`,children:t.title})]})]})}function x({icon:e}){return e===`success`?(0,c.jsx)(`svg`,{className:`dmui-toast__icon`,viewBox:`0 0 24 24`,"aria-hidden":`true`,children:(0,c.jsx)(`path`,{d:`M5 13l4 4L19 7`})}):e===`error`?(0,c.jsx)(`svg`,{className:`dmui-toast__icon`,viewBox:`0 0 24 24`,"aria-hidden":`true`,children:(0,c.jsx)(`path`,{d:`M6 6l12 12M18 6L6 18`})}):e===`loading`?(0,c.jsx)(`span`,{className:`dmui-toast__spinner`,"aria-hidden":`true`}):null}function S({dialog:e}){let[t,n]=(0,i.useState)(``),r=(0,i.useRef)(null);return(0,i.useEffect)(()=>{e.editable&&r.current?.focus()},[e.editable]),(0,c.jsxs)(`div`,{className:`dmui-overlay`,children:[(0,c.jsx)(`div`,{className:`dmui-mask`}),(0,c.jsxs)(`div`,{className:`dmui-modal`,role:`dialog`,"aria-modal":`true`,children:[e.title&&(0,c.jsx)(`div`,{className:`dmui-modal__title`,children:e.title}),e.editable?(0,c.jsx)(`input`,{ref:r,className:`dmui-modal__input`,value:t,placeholder:e.placeholderText,onChange:e=>n(e.target.value)}):e.content&&(0,c.jsx)(`div`,{className:`dmui-modal__content`,children:e.content}),(0,c.jsxs)(`div`,{className:`dmui-modal__actions`,children:[e.showCancel&&(0,c.jsx)(`button`,{type:`button`,className:`dmui-modal__button`,style:{color:e.cancelColor},onClick:()=>e.onResult(!1),children:e.cancelText}),(0,c.jsx)(`button`,{type:`button`,className:`dmui-modal__button`,style:{color:e.confirmColor},onClick:()=>e.onResult(!0,t),children:e.confirmText})]})]})]})}function C({dialog:e}){return(0,c.jsxs)(`div`,{className:`dmui-overlay`,children:[(0,c.jsx)(`div`,{className:`dmui-mask`,onClick:()=>e.onSelect(-1)}),(0,c.jsxs)(`div`,{className:`dmui-action-sheet`,role:`menu`,children:[(0,c.jsx)(`div`,{className:`dmui-action-sheet__items`,children:e.itemList.map((t,n)=>(0,c.jsx)(`button`,{type:`button`,className:`dmui-action-sheet__item`,style:{color:e.itemColor},onClick:()=>e.onSelect(n),children:t},n))}),(0,c.jsx)(`button`,{type:`button`,className:`dmui-action-sheet__cancel`,onClick:()=>e.onSelect(-1),children:`取消`})]})]})}function w(e){if(!e)return{config:null,visible:!1,badges:[],redDots:[]};let t=e.list.length;return{config:T(e),visible:!0,badges:Array.from({length:t},()=>``),redDots:Array.from({length:t},()=>!1)}}function T(e){return{...e,list:e.list.map(e=>({...e}))}}function E(e,t){switch(t.kind){case`reset`:return{state:w(t.config),ok:!0,errMsg:`reset:ok`};case`visibility`:return{state:{...e,visible:t.visible},ok:!0,errMsg:t.visible?`showTabBar:ok`:`hideTabBar:ok`};case`apply`:return D(e,t.name,t.params)}}function D(e,t,n){if(!e.config)return{state:e,ok:!1,errMsg:`${t}:fail tabBar not configured`};switch(t){case`setTabBarStyle`:return O(e,n);case`setTabBarItem`:return k(e,n);case`showTabBar`:return{state:{...e,visible:!0},ok:!0,errMsg:`showTabBar:ok`};case`hideTabBar`:return{state:{...e,visible:!1},ok:!0,errMsg:`hideTabBar:ok`};case`setTabBarBadge`:return A(e,n);case`removeTabBarBadge`:return j(e,n);case`showTabBarRedDot`:return M(e,n,!0);case`hideTabBarRedDot`:return M(e,n,!1)}}function O(e,t){if(!e.config)return{state:e,ok:!1,errMsg:`setTabBarStyle:fail tabBar not configured`};let n={...e.config},r=(e,t)=>{let r=P(t);r&&(n[e]=r)};return r(`color`,t.color),r(`selectedColor`,t.selectedColor),r(`backgroundColor`,t.backgroundColor),(t.borderStyle===`black`||t.borderStyle===`white`)&&(n.borderStyle=t.borderStyle),{state:{...e,config:n},ok:!0,errMsg:`setTabBarStyle:ok`}}function k(e,t){let n=N(e,t);if(n.err)return{state:e,ok:!1,errMsg:`setTabBarItem:fail ${n.err}`};if(!e.config)return{state:e,ok:!1,errMsg:`setTabBarItem:fail tabBar not configured`};let r=e.config.list[n.index],i={...r,text:typeof t.text==`string`?t.text:r.text,iconPath:typeof t.iconPath==`string`?t.iconPath:r.iconPath,selectedIconPath:typeof t.selectedIconPath==`string`?t.selectedIconPath:r.selectedIconPath},a=[...e.config.list];return a[n.index]=i,{state:{...e,config:{...e.config,list:a}},ok:!0,errMsg:`setTabBarItem:ok`}}function A(e,t){let n=N(e,t);if(n.err)return{state:e,ok:!1,errMsg:`setTabBarBadge:fail ${n.err}`};let r=[...e.badges];r[n.index]=String(t.text??``);let i=[...e.redDots];return i[n.index]=!1,{state:{...e,badges:r,redDots:i},ok:!0,errMsg:`setTabBarBadge:ok`}}function j(e,t){let n=N(e,t);if(n.err)return{state:e,ok:!1,errMsg:`removeTabBarBadge:fail ${n.err}`};let r=[...e.badges];return r[n.index]=``,{state:{...e,badges:r},ok:!0,errMsg:`removeTabBarBadge:ok`}}function M(e,t,n){let r=N(e,t);if(r.err)return{state:e,ok:!1,errMsg:`${n?`showTabBarRedDot`:`hideTabBarRedDot`}:fail ${r.err}`};let i=[...e.redDots];i[r.index]=n;let a=[...e.badges];return n&&(a[r.index]=``),{state:{...e,redDots:i,badges:a},ok:!0,errMsg:`${n?`showTabBarRedDot`:`hideTabBarRedDot`}:ok`}}function N(e,t){let n=e.config?.list??[],r=t.index,i=Number(r);return n.length?r==null||!Number.isInteger(i)||i<0||i>=n.length?{index:-1,err:`invalid index ${r}`}:{index:i,err:null}:{index:-1,err:`tabBar not configured`}}function P(e){if(typeof e!=`string`)return null;let t=e.trim();return!t||t.length>64?null:/[<>"';{}()\\]/.test(t)?/^(?:rgb|rgba|hsl|hsla)\(\s*[\d.,%\s/-]+\)$/i.test(t)?t:null:t}function F(e){return e?e.replace(/^\/+/,``):``}function I(e){let[t,n]=(typeof e==`string`?e:``).split(`?`),r={};if(n)for(let e of n.split(`&`)){if(!e)continue;let t=e.indexOf(`=`),n=t>=0?e.slice(0,t):e,i=t>=0?e.slice(t+1):``;n&&(r[decodeURIComponent(n)]=decodeURIComponent(i))}return{pagePath:F(t),query:r}}function L(e){let t={};return e.isTab&&(t[e.pagePath]=[e]),{stack:[e],tabStacks:t,currentTabPath:e.isTab?e.pagePath:null}}function R(e){return e.currentTabPath?{...e.tabStacks,[e.currentTabPath]:[...e.stack]}:e.tabStacks}function z(e,t){let n=e.stack[e.stack.length-1],r=[...e.stack,t];return{next:{...e,stack:r,tabStacks:e.currentTabPath?{...e.tabStacks,[e.currentTabPath]:r}:e.tabStacks},effects:n?[{kind:`lifecycle`,bridgeId:n.bridgeId,event:`pageHide`}]:[]}}function B(e,t){if(e.stack.length<=1)return{error:`no page to back`};let n=Math.min(Math.max(1,Number.isFinite(t)?t:1),e.stack.length-1),r=e.stack.slice(e.stack.length-n),i=e.stack.slice(0,e.stack.length-n),a=i[i.length-1],o={...e,stack:i,tabStacks:e.currentTabPath?{...e.tabStacks,[e.currentTabPath]:i}:e.tabStacks,currentTabPath:a.isTab?a.pagePath:e.currentTabPath},s=[];for(let e of r)s.push({kind:`lifecycle`,bridgeId:e.bridgeId,event:`pageUnload`}),s.push({kind:`closePage`,bridgeId:e.bridgeId});return s.push({kind:`lifecycle`,bridgeId:a.bridgeId,event:`pageShow`}),{next:o,effects:s}}function V(e,t){let n=e.stack[e.stack.length-1],r=[...e.stack.slice(0,e.stack.length-1),t],i={...e,stack:r,tabStacks:e.currentTabPath?{...e.tabStacks,[e.currentTabPath]:r}:e.tabStacks},a=[];return n&&(a.push({kind:`lifecycle`,bridgeId:n.bridgeId,event:`pageUnload`}),a.push({kind:`closePage`,bridgeId:n.bridgeId})),{next:i,effects:a}}function H(e,t){let n=new Set;for(let t of e.stack)n.add(t.bridgeId);for(let t of Object.values(e.tabStacks))for(let e of t)n.add(e.bridgeId);n.delete(t.bridgeId);let r=t.isTab?{[t.pagePath]:[t]}:{},i={stack:[t],tabStacks:r,currentTabPath:t.isTab?t.pagePath:null},a=[];for(let e of n)a.push({kind:`lifecycle`,bridgeId:e,event:`pageUnload`}),a.push({kind:`closePage`,bridgeId:e});return{next:i,effects:a}}function U(e,t,n){let r=e.stack[e.stack.length-1],i=R(e),a,o=i[t];if(o&&o.length>0)a=o;else if(n)a=[n];else throw Error(`[page-stack] switchTab to ${t} requires either a cached substack or a freshly-opened entry`);let s={...e,stack:a,tabStacks:{...i,[t]:a},currentTabPath:t},c=a[a.length-1],l=[];return r&&r.bridgeId!==c.bridgeId&&l.push({kind:`lifecycle`,bridgeId:r.bridgeId,event:`pageHide`}),n||l.push({kind:`lifecycle`,bridgeId:c.bridgeId,event:`pageShow`}),{next:s,effects:l}}function W(e){let t=new Map,n=e.stack[e.stack.length-1]?.bridgeId,r=e=>{t.has(e.bridgeId)||t.set(e.bridgeId,{entry:e,visible:e.bridgeId===n})};for(let t of Object.values(e.tabStacks))for(let e of t)r(e);for(let t of e.stack)r(t);return Array.from(t.values())}function G(e,t){let n=e.navigationBarBackgroundColor??`#ffffff`,r=e.navigationBarTextStyle??`black`,i=e.navigationStyle??`default`;return f({title:e.navigationBarTitleText??t,backgroundColor:n,textStyle:r,style:i,homeButtonVisible:e.homeButton===!0})}function K(e,t,n){switch(t){case`setNavigationBarTitle`:return{...e,title:typeof n.title==`string`?n.title:e.title};case`setNavigationBarColor`:return J(e,n);case`showNavigationBarLoading`:return{...e,loading:!0};case`hideNavigationBarLoading`:return{...e,loading:!1};case`hideHomeButton`:return{...e,homeButtonVisible:!1};default:return e}}var q=[`linear`,`easeIn`,`easeOut`,`easeInOut`];function J(e,t){let n=typeof t.frontColor==`string`?t.frontColor.toLowerCase():void 0,r=n===`#ffffff`?`white`:n===`#000000`?`black`:e.textStyle,i=typeof t.backgroundColor==`string`?t.backgroundColor:e.backgroundColor,a=(()=>{let e=t.animation;if(!e||typeof e!=`object`)return;let n=e,r=typeof n.duration==`number`&&Number.isFinite(n.duration)?Math.max(0,n.duration):0,i=typeof n.timingFunc==`string`?n.timingFunc:`linear`;return{durationMs:r,timingFunc:q.includes(i)?i:`linear`}})();return{...e,textStyle:r,backgroundColor:i,colorAnimation:a}}function Y(e,t,n){let r=e=>e.bridgeId===t?{...e,navBar:n(e.navBar)}:e,i=e.stack.map(r),a={};for(let[t,n]of Object.entries(e.tabStacks))a[t]=n.map(r);return{...e,stack:i,tabStacks:a}}var X=44,Z=24,Q=44;function $({miniApp:e,bridgeId:t,platform:n=`ios`}){let[a,o]=(0,i.useState)(()=>e.getInitialDevice());(0,i.useEffect)(()=>e.onSimulatorEvent(r.DEVICE_CHANGE,o),[e]);let l=a?.safeAreaInsets.top??(n===`ios`?X:Z),u=a?.safeAreaInsets.bottom??0,f=a?.notchType??`none`,p=(0,i.useMemo)(()=>e.getRenderPreloadUrl(),[e]),g=(0,i.useMemo)(()=>e.getTabBarConfig(),[e]),_=(0,i.useMemo)(()=>({bridgeId:t,pagePath:F(e.pagePath),query:{...e.query},isTab:!!e.getTabBarConfig()?.list.some(t=>F(t.pagePath)===F(e.pagePath)),windowConfig:e.rootWindowConfig??{},navBar:G(e.rootWindowConfig??{},e.appId)}),[e,t]),[{shell:v,tabBar:b},x]=(0,i.useState)(()=>({shell:L(_),tabBar:w(g)})),S=(0,i.useRef)({shell:v,tabBar:b});(0,i.useEffect)(()=>{S.current={shell:v,tabBar:b}},[v,b]);let C=(0,i.useCallback)(t=>{for(let n of t)n.kind===`lifecycle`?e.notifyLifecycle(n.bridgeId,n.event):n.kind===`closePage`&&e.closePage(n.bridgeId)},[e]);(0,i.useEffect)(()=>e.onSimulatorEvent(r.NAV_BAR,e=>{x(t=>({...t,shell:Y(t.shell,e.bridgeId,t=>K(t,e.name,e.params))}))}),[e]),(0,i.useEffect)(()=>e.onSimulatorEvent(r.TAB_ACTION,t=>{let n=E(S.current.tabBar,{kind:`apply`,name:t.name,params:t.params});x(e=>({...e,tabBar:n.state})),e.notifyNavCallback({ok:n.ok,errMsg:n.errMsg,callbacks:t.callbacks})}),[e]);let T=(0,i.useCallback)(async t=>{let n=(n,r)=>e.notifyNavCallback({ok:n,errMsg:r,callbacks:t.callbacks});try{switch(t.name){case`navigateTo`:await ee(e,S,x,C,t,n);break;case`navigateBack`:te(S,x,C,t,n);break;case`redirectTo`:await ne(e,S,x,C,t,n);break;case`reLaunch`:await re(e,S,x,C,t,n);break;case`switchTab`:await ie(e,S,x,C,t,n);break}}catch(e){n(!1,`${t.name}:fail ${e instanceof Error?e.message:String(e)}`)}},[e,C]);(0,i.useEffect)(()=>e.onSimulatorEvent(r.NAV_ACTION,e=>{T(e)}),[T,e]),(0,i.useEffect)(()=>e.onSimulatorEvent(r.API_CALL,t=>{s(e,t.name,t.params,n=>{e.notifyApiResponse({requestId:t.requestId,ok:n.ok,result:n.result,errMsg:n.errMsg,keep:n.keep})})}),[e]);let D=(0,i.useCallback)(()=>{if(S.current.shell.stack.length<=1)return;let t=S.current.shell.stack;T({appSessionId:e.appSessionId??``,bridgeId:t[t.length-1].bridgeId,name:`navigateBack`,params:{delta:1},callbacks:{}})},[e,T]),O=(0,i.useCallback)(t=>{let n=S.current.shell;t===n.currentTabPath&&n.stack.length===1||T({appSessionId:e.appSessionId??``,bridgeId:n.stack[n.stack.length-1].bridgeId,name:`switchTab`,params:{url:`/${t}`},callbacks:{}})},[e,T]),k=v.stack[v.stack.length-1],A=W(v);return(0,i.useEffect)(()=>{e.notifyActivePage(k.bridgeId)},[e,k.bridgeId]),(0,i.useEffect)(()=>{e.notifyPageStack(v.stack.map(e=>({pagePath:e.pagePath,query:e.query})))},[e,v.stack]),(0,c.jsx)(`main`,{className:`device-shell-root`,children:(0,c.jsxs)(`section`,{className:`device-shell`,"aria-label":`Dimina simulator`,style:a?{width:a.screenWidth,height:a.screenHeight}:void 0,children:[(0,c.jsx)(m,{height:l,notchType:f,textStyle:k.navBar.textStyle}),(0,c.jsx)(d,{state:k.navBar,stackDepth:v.stack.length,platform:n,statusBarHeight:l,navBarHeight:Q,onBack:D}),(0,c.jsx)(`div`,{className:`device-shell__viewport`,children:A.map(({entry:t,visible:n})=>(0,c.jsx)(`webview`,{className:`device-shell__webview`,src:e.createRenderHostUrl(t.bridgeId,t.pagePath,t.isTab),preload:p,allowpopups:`true`,style:{display:n?`flex`:`none`,zIndex:n?100:1}},t.bridgeId))}),k.isTab&&(0,c.jsx)(h,{state:b,currentPath:v.currentTabPath,resourceBaseUrl:e.resourceBaseUrl,appId:e.appId,onSwitch:O,bottomInset:u}),(0,c.jsx)(y,{}),u>0&&(0,c.jsx)(`div`,{className:`device-shell__home-indicator`,style:{height:u},"aria-hidden":`true`})]})})}async function ee(e,t,n,r,i,a){let{pagePath:o,query:s}=I(i.params.url);if(!o){a(!1,`navigateTo:fail invalid url`);return}if(e.getTabBarConfig()?.list.some(e=>F(e.pagePath)===o)){a(!1,`navigateTo:fail can not navigateTo a tabbar page`);return}let c=await e.openPage(o,s),l={bridgeId:c.bridgeId,pagePath:c.pagePath,query:s,isTab:c.isTab,windowConfig:c.windowConfig,navBar:G(c.windowConfig,e.appId)},{next:u,effects:d}=z(t.current.shell,l);n(e=>({...e,shell:u})),r(d),a(!0,`navigateTo:ok`)}function te(e,t,n,r,i){let a=r.params.delta,o=Number.isFinite(Number(a))?Number(a):1,s=B(e.current.shell,o);if(`error`in s){i(!1,`navigateBack:fail ${s.error}`);return}t(e=>({...e,shell:s.next})),n(s.effects),i(!0,`navigateBack:ok`)}async function ne(e,t,n,r,i,a){let{pagePath:o,query:s}=I(i.params.url);if(!o){a(!1,`redirectTo:fail invalid url`);return}if(e.getTabBarConfig()?.list.some(e=>F(e.pagePath)===o)){a(!1,`redirectTo:fail can not redirectTo a tabbar page`);return}let c=await e.openPage(o,s),l={bridgeId:c.bridgeId,pagePath:c.pagePath,query:s,isTab:c.isTab,windowConfig:c.windowConfig,navBar:G(c.windowConfig,e.appId)},{next:u,effects:d}=V(t.current.shell,l);n(e=>({...e,shell:u})),r(d),a(!0,`redirectTo:ok`)}async function re(e,t,n,r,i,a){let{pagePath:o,query:s}=I(i.params.url);if(!o){a(!1,`reLaunch:fail invalid url`);return}let c=await e.openPage(o,s),l={bridgeId:c.bridgeId,pagePath:c.pagePath,query:s,isTab:c.isTab,windowConfig:c.windowConfig,navBar:G(c.windowConfig,e.appId)},{next:u,effects:d}=H(t.current.shell,l);n(e=>({...e,shell:u})),r(d),a(!0,`reLaunch:ok`)}async function ie(e,t,n,r,i,a){let{pagePath:o}=I(i.params.url);if(!o){a(!1,`switchTab:fail invalid url`);return}if(!e.getTabBarConfig()?.list.some(e=>F(e.pagePath)===o)){a(!1,`switchTab:fail not a tabBar page: ${o}`);return}let s=t.current.shell.tabStacks[o],c=null;if(!s||s.length===0){let t=await e.openPage(o,{});c={bridgeId:t.bridgeId,pagePath:t.pagePath,query:{},isTab:!0,windowConfig:t.windowConfig,navBar:G(t.windowConfig,e.appId)}}let{next:l,effects:u}=U(t.current.shell,o,c);n(e=>({...e,shell:l})),r(u),a(!0,`switchTab:ok`)}export{$ as DeviceShell};
2
- //# sourceMappingURL=device-shell-CT3LRnTB.js.map
1
+ import{n as e,r as t,t as n}from"./jsx-runtime-CDK-o-S0.js";import{t as r}from"./bridge-channels-zhsumfky.js";var i=t(),a=new Set([`audioListen`]);function o(e){return a.has(e)}function s(e,t,n,r){let i=e.apiRegistry[t];if(!i)return r({ok:!1,errMsg:`${t}:fail no handler`}),Promise.resolve();let a=o(t)||(n&&typeof n==`object`&&!Array.isArray(n)?n.keep===!0:!1);return new Promise(o=>{let s=!1,c=e=>{if(s){a&&e.ok&&r({...e,keep:!0});return}s=!0,r(a&&e.ok?{...e,keep:!0}:e),o()},l=Symbol(`sim-cb-success`),u=Symbol(`sim-cb-fail`),d=Symbol(`sim-cb-complete`),f=!1,p=Object.create(e);p.createCallbackFunction=e=>{if(e!=null)return(e===l||e===u)&&(f=!0),(...n)=>{let r=n[0];e===l?c({ok:!0,result:r}):e===u?c({ok:!1,errMsg:r&&typeof r==`object`&&`errMsg`in r?String(r.errMsg):`${t}:fail`,result:r}):e===d&&!a&&c({ok:!0,result:r})}};let m=n&&typeof n==`object`&&!Array.isArray(n)?{...n}:{};m.success=l,m.fail=u,m.complete=d;try{let e=i.call(p,m);if(e&&typeof e.then==`function`){Promise.resolve(e).then(e=>c({ok:!0,result:e}),e=>{c({ok:!1,errMsg:`${t}:fail ${e instanceof Error?e.message:String(e)}`})});return}if(s)return;if(a){o();return}if(f){o();return}c({ok:!0,result:e})}catch(e){c({ok:!1,errMsg:`${t}:fail ${e instanceof Error?e.message:String(e)}`})}})}var c=n();function l({platform:e,statusBarHeight:t,textStyle:n}){let r=e===`ios`?87:95,i=t+(e===`ios`?4:6),a=e===`ios`?7:10;return(0,c.jsxs)(`div`,{className:`menu-capsule menu-capsule--${n}`,style:{width:r,height:32,top:i,right:a},"aria-hidden":`true`,children:[(0,c.jsxs)(`div`,{className:`menu-capsule__more`,children:[(0,c.jsx)(`span`,{}),(0,c.jsx)(`span`,{}),(0,c.jsx)(`span`,{})]}),(0,c.jsx)(`div`,{className:`menu-capsule__divider`}),(0,c.jsx)(`div`,{className:`menu-capsule__close`,children:(0,c.jsx)(`svg`,{viewBox:`0 0 16 16`,width:`12`,height:`12`,"aria-hidden":`true`,children:(0,c.jsx)(`path`,{d:`M4 4l8 8M12 4l-8 8`,stroke:`currentColor`,strokeWidth:`1.5`,fill:`none`,strokeLinecap:`round`})})})]})}var u={linear:`linear`,easeIn:`ease-in`,easeOut:`ease-out`,easeInOut:`ease-in-out`};function d({state:e,stackDepth:t,platform:n,statusBarHeight:r,navBarHeight:a,onBack:o,onHome:s}){let d=(0,i.useMemo)(()=>{if(!e.colorAnimation||e.colorAnimation.durationMs<=0)return;let t=u[e.colorAnimation.timingFunc]??`linear`;return`background-color ${e.colorAnimation.durationMs}ms ${t}, color ${e.colorAnimation.durationMs}ms ${t}`},[e.colorAnimation]),f=e.style===`custom`,p=t>1,m=!p&&e.homeButtonVisible,h=n===`ios`?`center`:`left`,g={backgroundColor:e.backgroundColor,color:e.textStyle===`white`?`#ffffff`:`#000000`,height:r+a,paddingTop:r,transition:d};return(0,c.jsxs)(`header`,{className:`nav-bar nav-bar--${n} nav-bar--${e.textStyle}${f?` nav-bar--custom`:``}`,style:g,"aria-hidden":f,children:[!f&&(0,c.jsxs)(`div`,{className:`nav-bar__row`,style:{height:a,justifyContent:h===`center`?`center`:`flex-start`},children:[(p||m)&&(0,c.jsxs)(`div`,{className:`nav-bar__leading`,children:[p&&(0,c.jsx)(`button`,{type:`button`,className:`nav-bar__back`,"aria-label":`Back`,onClick:o,children:(0,c.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`24`,height:`24`,"aria-hidden":`true`,children:(0,c.jsx)(`path`,{d:`M15 18l-6-6 6-6`,stroke:`currentColor`,strokeWidth:`2`,fill:`none`,strokeLinecap:`round`,strokeLinejoin:`round`})})}),m&&(0,c.jsx)(`button`,{type:`button`,className:`nav-bar__home`,"aria-label":`Home`,onClick:s,children:(0,c.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`22`,height:`22`,"aria-hidden":`true`,children:(0,c.jsx)(`path`,{d:`M3 12l9-9 9 9M5 10v10h14V10`,stroke:`currentColor`,strokeWidth:`2`,fill:`none`,strokeLinecap:`round`,strokeLinejoin:`round`})})})]}),(0,c.jsxs)(`div`,{className:`nav-bar__title nav-bar__title--${h}`,style:{color:e.textStyle===`white`?`#ffffff`:`#000000`},children:[e.loading&&(0,c.jsx)(`span`,{className:`nav-bar__spinner`,"aria-hidden":`true`}),(0,c.jsx)(`span`,{className:`nav-bar__title-text`,children:e.title})]})]}),(0,c.jsx)(l,{platform:n,statusBarHeight:r,textStyle:e.textStyle})]})}function f(e){return{title:e?.title??``,backgroundColor:e?.backgroundColor??`#000000`,textStyle:e?.textStyle??`white`,style:e?.style??`default`,loading:e?.loading??!1,homeButtonVisible:e?.homeButtonVisible??!1,colorAnimation:e?.colorAnimation}}function p(e){switch(e){case`notch`:return{width:164,height:30,top:0,bottomOnly:!0};case`dynamic-island`:return{width:124,height:36,top:11,bottomOnly:!1};default:return null}}function m({height:e,notchType:t,textStyle:n}){let r=p(t);return(0,c.jsxs)(`div`,{className:`device-statusbar`,style:{height:e,color:n===`black`?`#000000`:`#ffffff`},"aria-hidden":`true`,children:[(0,c.jsx)(`span`,{className:`device-statusbar__time`,children:`9:41`}),r&&(0,c.jsx)(`div`,{className:`device-statusbar__notch`,style:{width:r.width,height:r.height,top:r.top,borderRadius:r.bottomOnly?`0 0 ${Math.round(r.height*.6)}px ${Math.round(r.height*.6)}px`:`${r.height/2}px`}}),(0,c.jsxs)(`div`,{className:`device-statusbar__icons`,children:[(0,c.jsx)(`span`,{className:`device-statusbar__signal`}),(0,c.jsx)(`span`,{className:`device-statusbar__wifi`}),(0,c.jsx)(`span`,{className:`device-statusbar__battery`})]})]})}function h({state:e,currentPath:t,resourceBaseUrl:n,appId:r,onSwitch:i,bottomInset:a=0}){if(!e.config||!e.visible)return null;let{color:o,selectedColor:s,backgroundColor:l,borderStyle:u,list:d}=e.config,f=o||`#999999`,p=s||`#1890ff`;return(0,c.jsx)(`div`,{className:`dmb-tab-bar`,style:{backgroundColor:l||`#ffffff`,borderTopColor:u===`white`?`#ffffff`:`#e0e0e0`,paddingBottom:a},role:`tablist`,"aria-label":`TabBar`,children:d.map((a,o)=>{let s=g(a.pagePath),l=s===t,u=_(l?a.selectedIconPath??a.iconPath:a.iconPath,n,r),d=e.badges[o]??``,m=e.redDots[o]??!1;return(0,c.jsxs)(`button`,{type:`button`,className:`dmb-tab-bar__item${l?` is-selected`:``}`,role:`tab`,"aria-selected":l,onClick:()=>i(s),children:[u&&(0,c.jsx)(`span`,{className:`dmb-tab-bar__icon-slot`,children:(0,c.jsx)(`img`,{className:`dmb-tab-bar__icon`,src:u,alt:``,onError:e=>{e.currentTarget.style.display=`none`}})}),(0,c.jsx)(`span`,{className:`dmb-tab-bar__text`,style:{color:l?p:f},children:a.text||``}),d&&(0,c.jsx)(`span`,{className:`dmb-tab-bar__badge`,children:d}),!d&&m&&(0,c.jsx)(`span`,{className:`dmb-tab-bar__red-dot`})]},`${s}-${o}`)})})}function g(e){return e?e.replace(/^\/+/,``):``}function _(e,t,n){if(!e)return null;let r=e.trim();if(!r)return null;if(/^(?:data:|blob:|https?:|\/\/)/i.test(r))return r;if(!t)return null;let i=r.replace(/^\/+/,``).replace(/^\.\//,``);return i.startsWith(`${n}/`)?v(t,i):v(t,`${n}/main/${i}`)}function v(e,t){return`${e.endsWith(`/`)?e:`${e}/`}${t.replace(/^\/+/,``)}`}function y(){let[{toast:t,dialog:n},r]=(0,i.useState)(()=>e.getState());return(0,i.useEffect)(()=>e.subscribe(r),[]),(0,c.jsxs)(c.Fragment,{children:[t&&(0,c.jsx)(b,{toast:t}),n?.kind===`modal`&&(0,c.jsx)(S,{dialog:n}),n?.kind===`actionSheet`&&(0,c.jsx)(C,{dialog:n})]})}function b({toast:t}){(0,i.useEffect)(()=>{if(!Number.isFinite(t.duration))return;let n=window.setTimeout(()=>e.dismissToast(t),t.duration);return()=>window.clearTimeout(n)},[t]);let n=t.icon!==`none`||!!t.image;return(0,c.jsxs)(`div`,{className:`dmui-overlay`,"aria-live":`polite`,children:[t.mask&&(0,c.jsx)(`div`,{className:`dmui-mask dmui-mask--transparent`}),(0,c.jsxs)(`div`,{className:`dmui-toast${n?``:` dmui-toast--text`}`,role:`alert`,children:[t.image?(0,c.jsx)(`img`,{className:`dmui-toast__image`,src:t.image,alt:``}):(0,c.jsx)(x,{icon:t.icon}),t.title&&(0,c.jsx)(`div`,{className:`dmui-toast__title`,children:t.title})]})]})}function x({icon:e}){return e===`success`?(0,c.jsx)(`svg`,{className:`dmui-toast__icon`,viewBox:`0 0 24 24`,"aria-hidden":`true`,children:(0,c.jsx)(`path`,{d:`M5 13l4 4L19 7`})}):e===`error`?(0,c.jsx)(`svg`,{className:`dmui-toast__icon`,viewBox:`0 0 24 24`,"aria-hidden":`true`,children:(0,c.jsx)(`path`,{d:`M6 6l12 12M18 6L6 18`})}):e===`loading`?(0,c.jsx)(`span`,{className:`dmui-toast__spinner`,"aria-hidden":`true`}):null}function S({dialog:e}){let[t,n]=(0,i.useState)(``),r=(0,i.useRef)(null);return(0,i.useEffect)(()=>{e.editable&&r.current?.focus()},[e.editable]),(0,c.jsxs)(`div`,{className:`dmui-overlay`,children:[(0,c.jsx)(`div`,{className:`dmui-mask`}),(0,c.jsxs)(`div`,{className:`dmui-modal`,role:`dialog`,"aria-modal":`true`,children:[e.title&&(0,c.jsx)(`div`,{className:`dmui-modal__title`,children:e.title}),e.editable?(0,c.jsx)(`input`,{ref:r,className:`dmui-modal__input`,value:t,placeholder:e.placeholderText,onChange:e=>n(e.target.value)}):e.content&&(0,c.jsx)(`div`,{className:`dmui-modal__content`,children:e.content}),(0,c.jsxs)(`div`,{className:`dmui-modal__actions`,children:[e.showCancel&&(0,c.jsx)(`button`,{type:`button`,className:`dmui-modal__button`,style:{color:e.cancelColor},onClick:()=>e.onResult(!1),children:e.cancelText}),(0,c.jsx)(`button`,{type:`button`,className:`dmui-modal__button`,style:{color:e.confirmColor},onClick:()=>e.onResult(!0,t),children:e.confirmText})]})]})]})}function C({dialog:e}){return(0,c.jsxs)(`div`,{className:`dmui-overlay`,children:[(0,c.jsx)(`div`,{className:`dmui-mask`,onClick:()=>e.onSelect(-1)}),(0,c.jsxs)(`div`,{className:`dmui-action-sheet`,role:`menu`,children:[(0,c.jsx)(`div`,{className:`dmui-action-sheet__items`,children:e.itemList.map((t,n)=>(0,c.jsx)(`button`,{type:`button`,className:`dmui-action-sheet__item`,style:{color:e.itemColor},onClick:()=>e.onSelect(n),children:t},n))}),(0,c.jsx)(`button`,{type:`button`,className:`dmui-action-sheet__cancel`,onClick:()=>e.onSelect(-1),children:`取消`})]})]})}function w(e){if(!e)return{config:null,visible:!1,badges:[],redDots:[]};let t=e.list.length;return{config:T(e),visible:!0,badges:Array.from({length:t},()=>``),redDots:Array.from({length:t},()=>!1)}}function T(e){return{...e,list:e.list.map(e=>({...e}))}}function E(e,t){switch(t.kind){case`reset`:return{state:w(t.config),ok:!0,errMsg:`reset:ok`};case`visibility`:return{state:{...e,visible:t.visible},ok:!0,errMsg:t.visible?`showTabBar:ok`:`hideTabBar:ok`};case`apply`:return D(e,t.name,t.params)}}function D(e,t,n){if(!e.config)return{state:e,ok:!1,errMsg:`${t}:fail tabBar not configured`};switch(t){case`setTabBarStyle`:return O(e,n);case`setTabBarItem`:return k(e,n);case`showTabBar`:return{state:{...e,visible:!0},ok:!0,errMsg:`showTabBar:ok`};case`hideTabBar`:return{state:{...e,visible:!1},ok:!0,errMsg:`hideTabBar:ok`};case`setTabBarBadge`:return A(e,n);case`removeTabBarBadge`:return j(e,n);case`showTabBarRedDot`:return M(e,n,!0);case`hideTabBarRedDot`:return M(e,n,!1)}}function O(e,t){if(!e.config)return{state:e,ok:!1,errMsg:`setTabBarStyle:fail tabBar not configured`};let n={...e.config},r=(e,t)=>{let r=P(t);r&&(n[e]=r)};return r(`color`,t.color),r(`selectedColor`,t.selectedColor),r(`backgroundColor`,t.backgroundColor),(t.borderStyle===`black`||t.borderStyle===`white`)&&(n.borderStyle=t.borderStyle),{state:{...e,config:n},ok:!0,errMsg:`setTabBarStyle:ok`}}function k(e,t){let n=N(e,t);if(n.err)return{state:e,ok:!1,errMsg:`setTabBarItem:fail ${n.err}`};if(!e.config)return{state:e,ok:!1,errMsg:`setTabBarItem:fail tabBar not configured`};let r=e.config.list[n.index],i={...r,text:typeof t.text==`string`?t.text:r.text,iconPath:typeof t.iconPath==`string`?t.iconPath:r.iconPath,selectedIconPath:typeof t.selectedIconPath==`string`?t.selectedIconPath:r.selectedIconPath},a=[...e.config.list];return a[n.index]=i,{state:{...e,config:{...e.config,list:a}},ok:!0,errMsg:`setTabBarItem:ok`}}function A(e,t){let n=N(e,t);if(n.err)return{state:e,ok:!1,errMsg:`setTabBarBadge:fail ${n.err}`};let r=[...e.badges];r[n.index]=String(t.text??``);let i=[...e.redDots];return i[n.index]=!1,{state:{...e,badges:r,redDots:i},ok:!0,errMsg:`setTabBarBadge:ok`}}function j(e,t){let n=N(e,t);if(n.err)return{state:e,ok:!1,errMsg:`removeTabBarBadge:fail ${n.err}`};let r=[...e.badges];return r[n.index]=``,{state:{...e,badges:r},ok:!0,errMsg:`removeTabBarBadge:ok`}}function M(e,t,n){let r=N(e,t);if(r.err)return{state:e,ok:!1,errMsg:`${n?`showTabBarRedDot`:`hideTabBarRedDot`}:fail ${r.err}`};let i=[...e.redDots];i[r.index]=n;let a=[...e.badges];return n&&(a[r.index]=``),{state:{...e,redDots:i,badges:a},ok:!0,errMsg:`${n?`showTabBarRedDot`:`hideTabBarRedDot`}:ok`}}function N(e,t){let n=e.config?.list??[],r=t.index,i=Number(r);return n.length?r==null||!Number.isInteger(i)||i<0||i>=n.length?{index:-1,err:`invalid index ${r}`}:{index:i,err:null}:{index:-1,err:`tabBar not configured`}}function P(e){if(typeof e!=`string`)return null;let t=e.trim();return!t||t.length>64?null:/[<>"';{}()\\]/.test(t)?/^(?:rgb|rgba|hsl|hsla)\(\s*[\d.,%\s/-]+\)$/i.test(t)?t:null:t}function F(e){return e?e.replace(/^\/+/,``):``}function I(e){let[t,n]=(typeof e==`string`?e:``).split(`?`),r={};if(n)for(let e of n.split(`&`)){if(!e)continue;let t=e.indexOf(`=`),n=t>=0?e.slice(0,t):e,i=t>=0?e.slice(t+1):``;n&&(r[decodeURIComponent(n)]=decodeURIComponent(i))}return{pagePath:F(t),query:r}}function L(e){let t={};return e.isTab&&(t[e.pagePath]=[e]),{stack:[e],tabStacks:t,currentTabPath:e.isTab?e.pagePath:null}}function R(e){return e.currentTabPath?{...e.tabStacks,[e.currentTabPath]:[...e.stack]}:e.tabStacks}function z(e,t){let n=e.stack[e.stack.length-1],r=[...e.stack,t];return{next:{...e,stack:r,tabStacks:e.currentTabPath?{...e.tabStacks,[e.currentTabPath]:r}:e.tabStacks},effects:n?[{kind:`lifecycle`,bridgeId:n.bridgeId,event:`pageHide`}]:[]}}function B(e,t){if(e.stack.length<=1)return{error:`no page to back`};let n=Math.min(Math.max(1,Number.isFinite(t)?t:1),e.stack.length-1),r=e.stack.slice(e.stack.length-n),i=e.stack.slice(0,e.stack.length-n),a=i[i.length-1],o={...e,stack:i,tabStacks:e.currentTabPath?{...e.tabStacks,[e.currentTabPath]:i}:e.tabStacks,currentTabPath:a.isTab?a.pagePath:e.currentTabPath},s=[];for(let e of r)s.push({kind:`lifecycle`,bridgeId:e.bridgeId,event:`pageUnload`}),s.push({kind:`closePage`,bridgeId:e.bridgeId});return s.push({kind:`lifecycle`,bridgeId:a.bridgeId,event:`pageShow`}),{next:o,effects:s}}function V(e,t){let n=e.stack[e.stack.length-1],r=[...e.stack.slice(0,e.stack.length-1),t],i={...e,stack:r,tabStacks:e.currentTabPath?{...e.tabStacks,[e.currentTabPath]:r}:e.tabStacks},a=[];return n&&(a.push({kind:`lifecycle`,bridgeId:n.bridgeId,event:`pageUnload`}),a.push({kind:`closePage`,bridgeId:n.bridgeId})),{next:i,effects:a}}function H(e,t){let n=new Set;for(let t of e.stack)n.add(t.bridgeId);for(let t of Object.values(e.tabStacks))for(let e of t)n.add(e.bridgeId);n.delete(t.bridgeId);let r=t.isTab?{[t.pagePath]:[t]}:{},i={stack:[t],tabStacks:r,currentTabPath:t.isTab?t.pagePath:null},a=[];for(let e of n)a.push({kind:`lifecycle`,bridgeId:e,event:`pageUnload`}),a.push({kind:`closePage`,bridgeId:e});return{next:i,effects:a}}function U(e,t,n){let r=e.stack[e.stack.length-1],i=R(e),a,o=i[t];if(o&&o.length>0)a=o;else if(n)a=[n];else throw Error(`[page-stack] switchTab to ${t} requires either a cached substack or a freshly-opened entry`);let s={...e,stack:a,tabStacks:{...i,[t]:a},currentTabPath:t},c=a[a.length-1],l=[];return r&&r.bridgeId!==c.bridgeId&&l.push({kind:`lifecycle`,bridgeId:r.bridgeId,event:`pageHide`}),n||l.push({kind:`lifecycle`,bridgeId:c.bridgeId,event:`pageShow`}),{next:s,effects:l}}function W(e){let t=new Map,n=e.stack[e.stack.length-1]?.bridgeId,r=e=>{t.has(e.bridgeId)||t.set(e.bridgeId,{entry:e,visible:e.bridgeId===n})};for(let t of Object.values(e.tabStacks))for(let e of t)r(e);for(let t of e.stack)r(t);return Array.from(t.values())}function G(e,t){let n=e.navigationBarBackgroundColor??`#ffffff`,r=e.navigationBarTextStyle??`black`,i=e.navigationStyle??`default`;return f({title:e.navigationBarTitleText??t,backgroundColor:n,textStyle:r,style:i,homeButtonVisible:e.homeButton===!0})}function K(e,t,n){switch(t){case`setNavigationBarTitle`:return{...e,title:typeof n.title==`string`?n.title:e.title};case`setNavigationBarColor`:return J(e,n);case`showNavigationBarLoading`:return{...e,loading:!0};case`hideNavigationBarLoading`:return{...e,loading:!1};case`hideHomeButton`:return{...e,homeButtonVisible:!1};default:return e}}var q=[`linear`,`easeIn`,`easeOut`,`easeInOut`];function J(e,t){let n=typeof t.frontColor==`string`?t.frontColor.toLowerCase():void 0,r=n===`#ffffff`?`white`:n===`#000000`?`black`:e.textStyle,i=typeof t.backgroundColor==`string`?t.backgroundColor:e.backgroundColor,a=(()=>{let e=t.animation;if(!e||typeof e!=`object`)return;let n=e,r=typeof n.duration==`number`&&Number.isFinite(n.duration)?Math.max(0,n.duration):0,i=typeof n.timingFunc==`string`?n.timingFunc:`linear`;return{durationMs:r,timingFunc:q.includes(i)?i:`linear`}})();return{...e,textStyle:r,backgroundColor:i,colorAnimation:a}}function Y(e,t,n){let r=e=>e.bridgeId===t?{...e,navBar:n(e.navBar)}:e,i=e.stack.map(r),a={};for(let[t,n]of Object.entries(e.tabStacks))a[t]=n.map(r);return{...e,stack:i,tabStacks:a}}var X=44,Z=24,Q=44;function $({miniApp:e,bridgeId:t,platform:n=`ios`}){let[a,o]=(0,i.useState)(()=>e.getInitialDevice());(0,i.useEffect)(()=>e.onSimulatorEvent(r.DEVICE_CHANGE,o),[e]);let l=a?.safeAreaInsets.top??(n===`ios`?X:Z),u=a?.safeAreaInsets.bottom??0,f=a?.notchType??`none`,p=(0,i.useMemo)(()=>e.getRenderPreloadUrl(),[e]),g=(0,i.useMemo)(()=>e.getTabBarConfig(),[e]),_=(0,i.useMemo)(()=>({bridgeId:t,pagePath:F(e.pagePath),query:{...e.query},isTab:!!e.getTabBarConfig()?.list.some(t=>F(t.pagePath)===F(e.pagePath)),windowConfig:e.rootWindowConfig??{},navBar:G(e.rootWindowConfig??{},e.appId)}),[e,t]),[{shell:v,tabBar:b},x]=(0,i.useState)(()=>({shell:L(_),tabBar:w(g)})),S=(0,i.useRef)({shell:v,tabBar:b});(0,i.useEffect)(()=>{S.current={shell:v,tabBar:b}},[v,b]);let C=(0,i.useCallback)(t=>{for(let n of t)n.kind===`lifecycle`?e.notifyLifecycle(n.bridgeId,n.event):n.kind===`closePage`&&e.closePage(n.bridgeId)},[e]);(0,i.useEffect)(()=>e.onSimulatorEvent(r.NAV_BAR,e=>{x(t=>({...t,shell:Y(t.shell,e.bridgeId,t=>K(t,e.name,e.params))}))}),[e]),(0,i.useEffect)(()=>e.onSessionEvent(r.TAB_ACTION,t=>{let n=E(S.current.tabBar,{kind:`apply`,name:t.name,params:t.params});x(e=>({...e,tabBar:n.state})),e.notifyNavCallback({ok:n.ok,errMsg:n.errMsg,callbacks:t.callbacks})}),[e]);let T=(0,i.useCallback)(async t=>{let n=(n,r)=>e.notifyNavCallback({ok:n,errMsg:r,callbacks:t.callbacks});try{switch(t.name){case`navigateTo`:await ee(e,S,x,C,t,n);break;case`navigateBack`:te(S,x,C,t,n);break;case`redirectTo`:await ne(e,S,x,C,t,n);break;case`reLaunch`:await re(e,S,x,C,t,n);break;case`switchTab`:await ie(e,S,x,C,t,n);break}}catch(e){n(!1,`${t.name}:fail ${e instanceof Error?e.message:String(e)}`)}},[e,C]);(0,i.useEffect)(()=>e.onSessionEvent(r.NAV_ACTION,e=>{T(e)}),[T,e]),(0,i.useEffect)(()=>e.onSessionEvent(r.API_CALL,t=>{s(e,t.name,t.params,n=>{e.notifyApiResponse({requestId:t.requestId,ok:n.ok,result:n.result,errMsg:n.errMsg,keep:n.keep})})}),[e]);let D=(0,i.useCallback)(()=>{if(S.current.shell.stack.length<=1)return;let t=S.current.shell.stack;T({appSessionId:e.appSessionId??``,bridgeId:t[t.length-1].bridgeId,name:`navigateBack`,params:{delta:1},callbacks:{}})},[e,T]),O=(0,i.useCallback)(t=>{let n=S.current.shell;t===n.currentTabPath&&n.stack.length===1||T({appSessionId:e.appSessionId??``,bridgeId:n.stack[n.stack.length-1].bridgeId,name:`switchTab`,params:{url:`/${t}`},callbacks:{}})},[e,T]),k=v.stack[v.stack.length-1],A=W(v);return(0,i.useEffect)(()=>{e.notifyActivePage(k.bridgeId)},[e,k.bridgeId]),(0,i.useEffect)(()=>{e.notifyPageStack(v.stack.map(e=>({pagePath:e.pagePath,query:e.query})))},[e,v.stack]),(0,c.jsx)(`main`,{className:`device-shell-root`,children:(0,c.jsxs)(`section`,{className:`device-shell`,"aria-label":`Dimina simulator`,style:a?{width:a.screenWidth,height:a.screenHeight}:void 0,children:[(0,c.jsx)(m,{height:l,notchType:f,textStyle:k.navBar.textStyle}),(0,c.jsx)(d,{state:k.navBar,stackDepth:v.stack.length,platform:n,statusBarHeight:l,navBarHeight:Q,onBack:D}),(0,c.jsx)(`div`,{className:`device-shell__viewport`,children:A.map(({entry:t,visible:n})=>(0,c.jsx)(`webview`,{className:`device-shell__webview`,src:e.createRenderHostUrl(t.bridgeId,t.pagePath,t.isTab),preload:p,allowpopups:`true`,style:{display:n?`flex`:`none`,zIndex:n?100:1}},t.bridgeId))}),k.isTab&&(0,c.jsx)(h,{state:b,currentPath:v.currentTabPath,resourceBaseUrl:e.resourceBaseUrl,appId:e.appId,onSwitch:O,bottomInset:u}),(0,c.jsx)(y,{}),u>0&&(0,c.jsx)(`div`,{className:`device-shell__home-indicator`,style:{height:u},"aria-hidden":`true`})]})})}async function ee(e,t,n,r,i,a){let{pagePath:o,query:s}=I(i.params.url);if(!o){a(!1,`navigateTo:fail invalid url`);return}if(e.getTabBarConfig()?.list.some(e=>F(e.pagePath)===o)){a(!1,`navigateTo:fail can not navigateTo a tabbar page`);return}let c=await e.openPage(o,s),l={bridgeId:c.bridgeId,pagePath:c.pagePath,query:s,isTab:c.isTab,windowConfig:c.windowConfig,navBar:G(c.windowConfig,e.appId)},{next:u,effects:d}=z(t.current.shell,l);n(e=>({...e,shell:u})),r(d),a(!0,`navigateTo:ok`)}function te(e,t,n,r,i){let a=r.params.delta,o=Number.isFinite(Number(a))?Number(a):1,s=B(e.current.shell,o);if(`error`in s){i(!1,`navigateBack:fail ${s.error}`);return}t(e=>({...e,shell:s.next})),n(s.effects),i(!0,`navigateBack:ok`)}async function ne(e,t,n,r,i,a){let{pagePath:o,query:s}=I(i.params.url);if(!o){a(!1,`redirectTo:fail invalid url`);return}if(e.getTabBarConfig()?.list.some(e=>F(e.pagePath)===o)){a(!1,`redirectTo:fail can not redirectTo a tabbar page`);return}let c=await e.openPage(o,s),l={bridgeId:c.bridgeId,pagePath:c.pagePath,query:s,isTab:c.isTab,windowConfig:c.windowConfig,navBar:G(c.windowConfig,e.appId)},{next:u,effects:d}=V(t.current.shell,l);n(e=>({...e,shell:u})),r(d),a(!0,`redirectTo:ok`)}async function re(e,t,n,r,i,a){let{pagePath:o,query:s}=I(i.params.url);if(!o){a(!1,`reLaunch:fail invalid url`);return}let c=await e.openPage(o,s),l={bridgeId:c.bridgeId,pagePath:c.pagePath,query:s,isTab:c.isTab,windowConfig:c.windowConfig,navBar:G(c.windowConfig,e.appId)},{next:u,effects:d}=H(t.current.shell,l);n(e=>({...e,shell:u})),r(d),a(!0,`reLaunch:ok`)}async function ie(e,t,n,r,i,a){let{pagePath:o}=I(i.params.url);if(!o){a(!1,`switchTab:fail invalid url`);return}if(!e.getTabBarConfig()?.list.some(e=>F(e.pagePath)===o)){a(!1,`switchTab:fail not a tabBar page: ${o}`);return}let s=t.current.shell.tabStacks[o],c=null;if(!s||s.length===0){let t=await e.openPage(o,{});c={bridgeId:t.bridgeId,pagePath:t.pagePath,query:{},isTab:!0,windowConfig:t.windowConfig,navBar:G(t.windowConfig,e.appId)}}let{next:l,effects:u}=U(t.current.shell,o,c);n(e=>({...e,shell:l})),r(u),a(!0,`switchTab:ok`)}export{$ as DeviceShell};
2
+ //# sourceMappingURL=device-shell-CUl0ILfn.js.map