@dimina-kit/devtools 0.4.0-dev.20260703051110 → 0.4.0-dev.20260703101348

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 (55) hide show
  1. package/dist/main/index.bundle.js +395 -49
  2. package/dist/main/ipc/bridge-router.d.ts +8 -0
  3. package/dist/main/ipc/bridge-router.js +352 -38
  4. package/dist/main/services/console-forward/index.d.ts +12 -1
  5. package/dist/main/services/console-forward/index.js +99 -1
  6. package/dist/main/services/diagnostics/index.d.ts +49 -0
  7. package/dist/main/services/diagnostics/index.js +61 -0
  8. package/dist/main/services/network-forward/index.js +32 -0
  9. package/dist/main/services/notifications/renderer-notifier.d.ts +39 -0
  10. package/dist/main/services/notifications/renderer-notifier.js +4 -1
  11. package/dist/main/services/projects/project-repository.js +2 -1
  12. package/dist/main/services/views/simulator-session-policy.js +17 -0
  13. package/dist/main/services/workbench-context.d.ts +10 -0
  14. package/dist/main/services/workspace/workspace-service.js +12 -3
  15. package/dist/main/windows/service-host-window/create.d.ts +15 -1
  16. package/dist/main/windows/service-host-window/create.js +11 -3
  17. package/dist/preload/shared/api-compat.js +18 -55
  18. package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
  19. package/dist/preload/windows/main.cjs.map +1 -1
  20. package/dist/preload/windows/simulator.cjs +117 -44
  21. package/dist/preload/windows/simulator.cjs.map +3 -3
  22. package/dist/preload/windows/simulator.js +117 -44
  23. package/dist/renderer/assets/index-BwzPwCmM.js +49 -0
  24. package/dist/renderer/assets/{input-Cjk0wSEh.js → input-CTb_le7F.js} +2 -2
  25. package/dist/renderer/assets/ipc-transport-BPWIV5hA.css +1 -0
  26. package/dist/renderer/assets/{ipc-transport-OZS-KmOW.js → ipc-transport-Ck5Xa8Tu.js} +2 -2
  27. package/dist/renderer/assets/popover-B1Zu2UQu.js +2 -0
  28. package/dist/renderer/assets/{select-BQDXi5ih.js → select-ozSk5Pt6.js} +2 -2
  29. package/dist/renderer/assets/{settings-tP3Px2KR.js → settings-CNwGOI22.js} +2 -2
  30. package/dist/renderer/assets/settings-api-DMbMp1Eq.js +2 -0
  31. package/dist/renderer/assets/{workbenchSettings-COhuFF-i.js → workbenchSettings-Cr4EHo5w.js} +2 -2
  32. package/dist/renderer/entries/main/index.html +6 -6
  33. package/dist/renderer/entries/popover/index.html +5 -5
  34. package/dist/renderer/entries/settings/index.html +5 -5
  35. package/dist/renderer/entries/workbench-settings/index.html +4 -4
  36. package/dist/shared/bridge-channels.d.ts +22 -0
  37. package/dist/shared/ipc-channels.d.ts +3 -0
  38. package/dist/shared/ipc-channels.js +9 -0
  39. package/dist/shared/request-core.d.ts +84 -0
  40. package/dist/shared/request-core.js +168 -0
  41. package/dist/shared/simulator-api-metadata.d.ts +22 -17
  42. package/dist/shared/simulator-api-metadata.js +36 -0
  43. package/dist/shared/types.d.ts +7 -4
  44. package/dist/simulator/assets/{device-shell-CiLAPa0I.js → device-shell-C-wcFq3Z.js} +2 -2
  45. package/dist/simulator/assets/{jsx-runtime-CDK-o-S0.js → jsx-runtime-BDTY6fEq.js} +2 -2
  46. package/dist/simulator/assets/simulator-DU3-fS3v.js +10 -0
  47. package/dist/simulator/assets/simulator-mini-app-DzfMfnVM.js +2 -0
  48. package/dist/simulator/simulator.html +2 -2
  49. package/package.json +6 -6
  50. package/dist/renderer/assets/index-D-ksyN1p.js +0 -49
  51. package/dist/renderer/assets/ipc-transport-D5dKIti1.css +0 -1
  52. package/dist/renderer/assets/popover-CQVvOe90.js +0 -2
  53. package/dist/renderer/assets/settings-api-B6x2mhaD.js +0 -2
  54. package/dist/simulator/assets/simulator-Dvnxry3y.js +0 -10
  55. package/dist/simulator/assets/simulator-mini-app-Bt639XL_.js +0 -2
@@ -26,13 +26,13 @@
26
26
  overflow: hidden;
27
27
  }
28
28
  </style>
29
- <script type="module" crossorigin src="../../assets/index-D-ksyN1p.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">
29
+ <script type="module" crossorigin src="../../assets/index-BwzPwCmM.js"></script>
30
+ <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-Ck5Xa8Tu.js">
31
+ <link rel="modulepreload" crossorigin href="../../assets/input-CTb_le7F.js">
32
+ <link rel="modulepreload" crossorigin href="../../assets/select-ozSk5Pt6.js">
33
+ <link rel="modulepreload" crossorigin href="../../assets/settings-api-DMbMp1Eq.js">
34
34
  <link rel="modulepreload" crossorigin href="../../assets/constants-EAMiwL9_.js">
35
- <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-D5dKIti1.css">
35
+ <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-BPWIV5hA.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-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">
11
+ <script type="module" crossorigin src="../../assets/popover-B1Zu2UQu.js"></script>
12
+ <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-Ck5Xa8Tu.js">
13
+ <link rel="modulepreload" crossorigin href="../../assets/input-CTb_le7F.js">
14
+ <link rel="modulepreload" crossorigin href="../../assets/select-ozSk5Pt6.js">
15
15
  <link rel="modulepreload" crossorigin href="../../assets/constants-EAMiwL9_.js">
16
- <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-D5dKIti1.css">
16
+ <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-BPWIV5hA.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-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">
14
+ <script type="module" crossorigin src="../../assets/settings-CNwGOI22.js"></script>
15
+ <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-Ck5Xa8Tu.js">
16
+ <link rel="modulepreload" crossorigin href="../../assets/input-CTb_le7F.js">
17
+ <link rel="modulepreload" crossorigin href="../../assets/settings-api-DMbMp1Eq.js">
18
+ <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-BPWIV5hA.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-COhuFF-i.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">
9
+ <script type="module" crossorigin src="../../assets/workbenchSettings-Cr4EHo5w.js"></script>
10
+ <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-Ck5Xa8Tu.js">
11
+ <link rel="modulepreload" crossorigin href="../../assets/settings-api-DMbMp1Eq.js">
12
12
  <link rel="modulepreload" crossorigin href="../../assets/constants-EAMiwL9_.js">
13
- <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-D5dKIti1.css">
13
+ <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-BPWIV5hA.css">
14
14
  </head>
15
15
  <body>
16
16
  <div id="root"></div>
@@ -198,6 +198,16 @@ export interface AppManifest {
198
198
  entryPagePath: string;
199
199
  pages: string[];
200
200
  tabBar?: TabBarConfig;
201
+ /**
202
+ * Provenance of this manifest: `'app-config'` when built from a real
203
+ * compiled `app-config.json` (its `pages` list is authoritative, so mount
204
+ * gates can validate membership against it); `'fallback'` when
205
+ * app-config.json was unreachable and the manifest is a single-page stand-in
206
+ * built from the spawn request. Mount gates only enforce against
207
+ * `'app-config'` — a `'fallback'` manifest has no compiled truth to check
208
+ * membership against, so it must let every page/nav target through.
209
+ */
210
+ source: 'app-config' | 'fallback';
201
211
  }
202
212
  export interface SpawnRequest {
203
213
  simulatorWcId?: number;
@@ -224,7 +234,19 @@ export interface SpawnRequest {
224
234
  export interface SpawnResult {
225
235
  appSessionId: string;
226
236
  bridgeId: string;
237
+ /** The pagePath originally requested (unchanged even when a fallback applied — see `resolvedPagePath`). */
227
238
  pagePath: string;
239
+ /**
240
+ * The pagePath the root PageSession was ACTUALLY spawned with. Equal to
241
+ * `pagePath` unless `pageFallbackApplied` is true, in which case the request
242
+ * was absent from `manifest.pages` and this is `manifest.entryPagePath`
243
+ * (or `manifest.pages[0]` when even that isn't a member). Callers that cache
244
+ * "the current page" (e.g. `SimulatorMiniApp`) must reconcile against this,
245
+ * not the original request.
246
+ */
247
+ resolvedPagePath: string;
248
+ /** Whether `resolvedPagePath` differs from the request because it was absent from the compiled manifest. Always false for a `'fallback'` manifest (nothing to validate against). */
249
+ pageFallbackApplied: boolean;
228
250
  serviceWcId: number;
229
251
  resourceBaseUrl: string;
230
252
  manifest: AppManifest;
@@ -165,6 +165,9 @@ export declare const ProjectChannel: {
165
165
  readonly CaptureThumbnail: "project:captureThumbnail";
166
166
  readonly GetThumbnail: "project:getThumbnail";
167
167
  };
168
+ export declare const SessionChannel: {
169
+ readonly RuntimeStatus: "session:runtimeStatus";
170
+ };
168
171
  export declare const ProjectFsChannel: {
169
172
  readonly GetRoot: "project:fs:getRoot";
170
173
  readonly ReadFile: "project:fs:readFile";
@@ -130,6 +130,15 @@ export const ProjectChannel = {
130
130
  CaptureThumbnail: 'project:captureThumbnail',
131
131
  GetThumbnail: 'project:getThumbnail',
132
132
  };
133
+ // ── Session runtime status ───────────────────────────────────────────────
134
+ //
135
+ // Main → renderer push of the post-compile SESSION lifecycle (spawn → running
136
+ // → crash/timeout), distinct from `ProjectChannel.Status` which only tracks
137
+ // compile outcomes. Compile succeeding tells the renderer nothing about
138
+ // whether the simulator actually booted — this channel closes that gap.
139
+ export const SessionChannel = {
140
+ RuntimeStatus: 'session:runtimeStatus',
141
+ };
133
142
  // ── Project file system (sandboxed to active project root) ────────────────
134
143
  //
135
144
  // Read/write access to the active project's files, used by the in-renderer
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Single authoritative implementation of wx.request network semantics, shared
3
+ * by every request surface (simulator `directRequest`, preload api-compat
4
+ * `wx.request` shim). Keeping the semantics in one module is what prevents the
5
+ * surfaces from drifting apart on the core contract.
6
+ *
7
+ * The contract (official wx.request semantics):
8
+ * - success vs fail is decided ONLY by whether a server response was
9
+ * received. Any HTTP response — 200, 401, 500 — resolves via `success`
10
+ * with `{ data, statusCode, header, errMsg: 'request:ok' }`; callers
11
+ * branch on `statusCode` (e.g. 401 → re-login).
12
+ * - `fail` fires only for network-layer failures and always carries a
13
+ * non-empty errMsg: 'request:fail timeout' (deadline hit),
14
+ * 'request:fail abort' (caller aborted), 'request:fail <reason>' (DNS/
15
+ * connection/protocol errors).
16
+ * - `timeout` defaults to 60000ms (the wx default) when omitted or
17
+ * non-positive — a request never hangs indefinitely.
18
+ * - `dataType` (default 'json') controls body decoding: 'json' attempts
19
+ * JSON.parse with raw-text fallback; anything else keeps raw text.
20
+ * `responseType: 'arraybuffer'` (or the legacy `dataType: 'arraybuffer'`
21
+ * spelling) yields an ArrayBuffer instead.
22
+ * - Outgoing headers merge case-insensitively via `Headers` so a caller's
23
+ * `content-type` in any casing wins exactly once; the `application/json`
24
+ * default applies only when the caller supplied none. Plain-object merges
25
+ * would keep both casings as distinct keys and comma-join them on the wire.
26
+ * - GET/HEAD serialize object `data` into URL query params (no body);
27
+ * other methods send string data verbatim, form-encode objects under
28
+ * application/x-www-form-urlencoded, and JSON-encode otherwise.
29
+ * - `complete` fires exactly once, after success or fail, with that same
30
+ * result object.
31
+ *
32
+ * Not provided: `cookies` on the success result — fetch() cannot read
33
+ * Set-Cookie response headers, so surfacing a fabricated list would lie.
34
+ */
35
+ export interface RequestSuccessResult {
36
+ data: unknown;
37
+ statusCode: number;
38
+ header: Record<string, string>;
39
+ errMsg: 'request:ok';
40
+ }
41
+ export interface RequestFailResult {
42
+ errMsg: string;
43
+ errno?: number;
44
+ }
45
+ export interface RequestHandle {
46
+ abort(): void;
47
+ }
48
+ export interface RequestCoreOptions {
49
+ url: string;
50
+ data?: unknown;
51
+ header?: Record<string, string>;
52
+ timeout?: number;
53
+ method?: string;
54
+ dataType?: string;
55
+ responseType?: string;
56
+ }
57
+ export interface RequestCoreCallbacks {
58
+ success?: (res: RequestSuccessResult) => void;
59
+ fail?: (err: RequestFailResult) => void;
60
+ complete?: (res: RequestSuccessResult | RequestFailResult) => void;
61
+ }
62
+ /**
63
+ * The wx.request default timeout budget. Exported as the single source of
64
+ * truth for every layer that reasons about a request's time budget — the
65
+ * bridge-router watchdog (apiCallWatchdogMs in simulator-api-metadata.ts)
66
+ * derives its window from this so the two cannot drift apart.
67
+ */
68
+ export declare const DEFAULT_REQUEST_TIMEOUT_MS = 60000;
69
+ /**
70
+ * Largest delay setTimeout honours (2^31-1 ms). Anything above overflows the
71
+ * signed-32-bit timer register and fires ~immediately (~1ms) instead of late —
72
+ * so an oversized caller timeout must be rejected, never passed through.
73
+ */
74
+ export declare const MAX_TIMEOUT_MS = 2147483647;
75
+ /**
76
+ * Resolve a caller-supplied wx timeout into a usable budget: a finite positive
77
+ * number within setTimeout's range is honoured; anything else (absent, 0,
78
+ * negative, NaN, Infinity, overflowing) falls back to the wx default. Shared
79
+ * by performRequest and the bridge-router watchdog (apiCallWatchdogMs) so the
80
+ * two layers can never disagree on what a valid timeout is.
81
+ */
82
+ export declare function resolveTimeoutBudgetMs(timeout: unknown): number;
83
+ export declare function performRequest(opts: RequestCoreOptions, callbacks: RequestCoreCallbacks): RequestHandle;
84
+ //# sourceMappingURL=request-core.d.ts.map
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Single authoritative implementation of wx.request network semantics, shared
3
+ * by every request surface (simulator `directRequest`, preload api-compat
4
+ * `wx.request` shim). Keeping the semantics in one module is what prevents the
5
+ * surfaces from drifting apart on the core contract.
6
+ *
7
+ * The contract (official wx.request semantics):
8
+ * - success vs fail is decided ONLY by whether a server response was
9
+ * received. Any HTTP response — 200, 401, 500 — resolves via `success`
10
+ * with `{ data, statusCode, header, errMsg: 'request:ok' }`; callers
11
+ * branch on `statusCode` (e.g. 401 → re-login).
12
+ * - `fail` fires only for network-layer failures and always carries a
13
+ * non-empty errMsg: 'request:fail timeout' (deadline hit),
14
+ * 'request:fail abort' (caller aborted), 'request:fail <reason>' (DNS/
15
+ * connection/protocol errors).
16
+ * - `timeout` defaults to 60000ms (the wx default) when omitted or
17
+ * non-positive — a request never hangs indefinitely.
18
+ * - `dataType` (default 'json') controls body decoding: 'json' attempts
19
+ * JSON.parse with raw-text fallback; anything else keeps raw text.
20
+ * `responseType: 'arraybuffer'` (or the legacy `dataType: 'arraybuffer'`
21
+ * spelling) yields an ArrayBuffer instead.
22
+ * - Outgoing headers merge case-insensitively via `Headers` so a caller's
23
+ * `content-type` in any casing wins exactly once; the `application/json`
24
+ * default applies only when the caller supplied none. Plain-object merges
25
+ * would keep both casings as distinct keys and comma-join them on the wire.
26
+ * - GET/HEAD serialize object `data` into URL query params (no body);
27
+ * other methods send string data verbatim, form-encode objects under
28
+ * application/x-www-form-urlencoded, and JSON-encode otherwise.
29
+ * - `complete` fires exactly once, after success or fail, with that same
30
+ * result object.
31
+ *
32
+ * Not provided: `cookies` on the success result — fetch() cannot read
33
+ * Set-Cookie response headers, so surfacing a fabricated list would lie.
34
+ */
35
+ /**
36
+ * The wx.request default timeout budget. Exported as the single source of
37
+ * truth for every layer that reasons about a request's time budget — the
38
+ * bridge-router watchdog (apiCallWatchdogMs in simulator-api-metadata.ts)
39
+ * derives its window from this so the two cannot drift apart.
40
+ */
41
+ export const DEFAULT_REQUEST_TIMEOUT_MS = 60_000;
42
+ /**
43
+ * Largest delay setTimeout honours (2^31-1 ms). Anything above overflows the
44
+ * signed-32-bit timer register and fires ~immediately (~1ms) instead of late —
45
+ * so an oversized caller timeout must be rejected, never passed through.
46
+ */
47
+ export const MAX_TIMEOUT_MS = 2_147_483_647;
48
+ /**
49
+ * Resolve a caller-supplied wx timeout into a usable budget: a finite positive
50
+ * number within setTimeout's range is honoured; anything else (absent, 0,
51
+ * negative, NaN, Infinity, overflowing) falls back to the wx default. Shared
52
+ * by performRequest and the bridge-router watchdog (apiCallWatchdogMs) so the
53
+ * two layers can never disagree on what a valid timeout is.
54
+ */
55
+ export function resolveTimeoutBudgetMs(timeout) {
56
+ const t = Number(timeout);
57
+ return Number.isFinite(t) && t > 0 && t <= MAX_TIMEOUT_MS ? t : DEFAULT_REQUEST_TIMEOUT_MS;
58
+ }
59
+ function buildHeaders(header) {
60
+ const headers = new Headers();
61
+ for (const [key, value] of Object.entries(header ?? {})) {
62
+ if (value != null)
63
+ headers.set(key, String(value));
64
+ }
65
+ if (!headers.has('content-type'))
66
+ headers.set('content-type', 'application/json');
67
+ return headers;
68
+ }
69
+ function appendQueryParams(url, data) {
70
+ // Resolve against the current document when available so page-relative URLs
71
+ // keep working in the render-window shim.
72
+ const base = typeof location !== 'undefined' ? location.href : undefined;
73
+ const resolved = new URL(url, base);
74
+ for (const [key, value] of Object.entries(data)) {
75
+ resolved.searchParams.append(key, String(value));
76
+ }
77
+ return resolved.toString();
78
+ }
79
+ function encodeBody(data, contentType) {
80
+ if (typeof data === 'string')
81
+ return data;
82
+ if (contentType.includes('application/x-www-form-urlencoded')) {
83
+ const form = new URLSearchParams();
84
+ for (const [key, value] of Object.entries(data)) {
85
+ form.append(key, String(value));
86
+ }
87
+ return form.toString();
88
+ }
89
+ return JSON.stringify(data);
90
+ }
91
+ async function decodeResponseData(response, dataType, responseType) {
92
+ if (responseType === 'arraybuffer' || dataType === 'arraybuffer') {
93
+ return response.arrayBuffer();
94
+ }
95
+ const text = await response.text();
96
+ if (dataType !== 'json')
97
+ return text;
98
+ try {
99
+ return JSON.parse(text);
100
+ }
101
+ catch {
102
+ return text;
103
+ }
104
+ }
105
+ export function performRequest(opts, callbacks) {
106
+ const method = (opts.method || 'GET').toUpperCase();
107
+ const canHaveBody = method !== 'GET' && method !== 'HEAD';
108
+ const headers = buildHeaders(opts.header);
109
+ let url = opts.url;
110
+ const init = { method, headers };
111
+ if (!canHaveBody) {
112
+ if (opts.data && typeof opts.data === 'object') {
113
+ url = appendQueryParams(url, opts.data);
114
+ }
115
+ }
116
+ else if (opts.data != null) {
117
+ init.body = encodeBody(opts.data, headers.get('content-type') ?? '');
118
+ }
119
+ const controller = new AbortController();
120
+ init.signal = controller.signal;
121
+ // First verdict wins: a timeout/abort settles the call even though the fetch
122
+ // promise is still pending, and the fetch's own late resolution/AbortError
123
+ // rejection must not fire a second callback round.
124
+ let settled = false;
125
+ function settleSuccess(res) {
126
+ if (settled)
127
+ return;
128
+ settled = true;
129
+ clearTimeout(timer);
130
+ callbacks.success?.(res);
131
+ callbacks.complete?.(res);
132
+ }
133
+ function settleFail(err) {
134
+ if (settled)
135
+ return;
136
+ settled = true;
137
+ clearTimeout(timer);
138
+ callbacks.fail?.(err);
139
+ callbacks.complete?.(err);
140
+ }
141
+ const timeoutMs = resolveTimeoutBudgetMs(opts.timeout);
142
+ const timer = setTimeout(() => {
143
+ settleFail({ errMsg: 'request:fail timeout' });
144
+ controller.abort();
145
+ }, timeoutMs);
146
+ const dataType = opts.dataType ?? 'json';
147
+ const responseType = opts.responseType ?? 'text';
148
+ fetch(url, init)
149
+ .then(async (response) => {
150
+ const header = {};
151
+ response.headers.forEach((value, key) => {
152
+ header[key] = value;
153
+ });
154
+ const data = await decodeResponseData(response, dataType, responseType);
155
+ settleSuccess({ data, statusCode: response.status, header, errMsg: 'request:ok' });
156
+ })
157
+ .catch((error) => {
158
+ const reason = error instanceof Error ? error.message : String(error);
159
+ settleFail({ errMsg: `request:fail ${reason || 'network error'}` });
160
+ });
161
+ return {
162
+ abort() {
163
+ settleFail({ errMsg: 'request:fail abort' });
164
+ controller.abort();
165
+ },
166
+ };
167
+ }
168
+ //# sourceMappingURL=request-core.js.map
@@ -1,21 +1,26 @@
1
+ export declare const PERSISTENT_SIMULATOR_APIS: ReadonlySet<string>;
2
+ export declare function isPersistentSimulatorApi(name: string): boolean;
1
3
  /**
2
- * Persistent (subscription) simulator APIs a call that, once made, keeps
3
- * delivering a response on every underlying event instead of settling once.
4
- *
5
- * The dimina service runtime strips `keep` / `evtId` / `success` before the
6
- * call leaves the service host (it stores them service-local in
7
- * `callback.store`), so by the time `audioListen` reaches the container its
8
- * `keep: true` intent is gone and it would degrade to a one-shot call —
9
- * dropping every audio DOM event after the first. The container and router
10
- * therefore recognise these APIs by NAME and treat them as persistent
11
- * regardless of the (stripped) params.
4
+ * APIs whose one-shot call legitimately runs as long as the caller's wx
5
+ * network timeout budget (`params.timeout`, default 60000ms) the simulator
6
+ * handler answers when the network answers, not within a fixed router window.
7
+ */
8
+ export declare const NETWORK_BUDGET_SIMULATOR_APIS: ReadonlySet<string>;
9
+ /**
10
+ * Flat watchdog window for forwarded one-shot calls whose handler is expected
11
+ * to answer promptly; it guards against a missing handler / dead seam.
12
+ */
13
+ export declare const API_CALL_WATCHDOG_MS = 5000;
14
+ /**
15
+ * How long bridge-router's one-shot "no handler" watchdog waits before
16
+ * tearing a forwarded simulator-API call down.
12
17
  *
13
- * Currently only `audioListen` the InnerAudioContext DOM-event bridge
14
- * (canplay / play / pause / ended / error / timeupdate / waiting / seeking /
15
- * seeked). Add any new subscription API here: this is the single source of
16
- * truth, consumed by `bridge-router` (skip the one-shot timeout, keep-alive
17
- * responses) and `run-api-async` (no premature settle, re-fire on every event).
18
+ * Network-budget APIs get their wx timeout budget plus the flat window as
19
+ * forwarding grace: the handler owns the real deadline (performRequest emits
20
+ * `request:fail timeout` at the budget), so the watchdog only has to catch
21
+ * the case where no verdict ever comes back. A flat 5s window here would
22
+ * kill any HTTP call slower than 5s and drop its late perfectly valid
23
+ * response. Every other API keeps the flat window.
18
24
  */
19
- export declare const PERSISTENT_SIMULATOR_APIS: ReadonlySet<string>;
20
- export declare function isPersistentSimulatorApi(name: string): boolean;
25
+ export declare function apiCallWatchdogMs(name: string, params: Record<string, unknown> | undefined): number;
21
26
  //# sourceMappingURL=simulator-api-metadata.d.ts.map
@@ -16,8 +16,44 @@
16
16
  * truth, consumed by `bridge-router` (skip the one-shot timeout, keep-alive
17
17
  * responses) and `run-api-async` (no premature settle, re-fire on every event).
18
18
  */
19
+ import { MAX_TIMEOUT_MS, resolveTimeoutBudgetMs } from './request-core.js';
19
20
  export const PERSISTENT_SIMULATOR_APIS = new Set(['audioListen']);
20
21
  export function isPersistentSimulatorApi(name) {
21
22
  return PERSISTENT_SIMULATOR_APIS.has(name);
22
23
  }
24
+ /**
25
+ * APIs whose one-shot call legitimately runs as long as the caller's wx
26
+ * network timeout budget (`params.timeout`, default 60000ms) — the simulator
27
+ * handler answers when the network answers, not within a fixed router window.
28
+ */
29
+ export const NETWORK_BUDGET_SIMULATOR_APIS = new Set([
30
+ 'request',
31
+ 'downloadFile',
32
+ 'uploadFile',
33
+ ]);
34
+ /**
35
+ * Flat watchdog window for forwarded one-shot calls whose handler is expected
36
+ * to answer promptly; it guards against a missing handler / dead seam.
37
+ */
38
+ export const API_CALL_WATCHDOG_MS = 5_000;
39
+ /**
40
+ * How long bridge-router's one-shot "no handler" watchdog waits before
41
+ * tearing a forwarded simulator-API call down.
42
+ *
43
+ * Network-budget APIs get their wx timeout budget plus the flat window as
44
+ * forwarding grace: the handler owns the real deadline (performRequest emits
45
+ * `request:fail timeout` at the budget), so the watchdog only has to catch
46
+ * the case where no verdict ever comes back. A flat 5s window here would
47
+ * kill any HTTP call slower than 5s and drop its late — perfectly valid —
48
+ * response. Every other API keeps the flat window.
49
+ */
50
+ export function apiCallWatchdogMs(name, params) {
51
+ if (!NETWORK_BUDGET_SIMULATOR_APIS.has(name))
52
+ return API_CALL_WATCHDOG_MS;
53
+ // resolveTimeoutBudgetMs rejects non-finite/oversized caller timeouts, and
54
+ // the final clamp keeps budget+grace inside setTimeout's range — an
55
+ // overflowing delay would wrap to ~1ms and fire the watchdog immediately.
56
+ const budget = resolveTimeoutBudgetMs(params?.timeout);
57
+ return Math.min(budget + API_CALL_WATCHDOG_MS, MAX_TIMEOUT_MS);
58
+ }
23
59
  //# sourceMappingURL=simulator-api-metadata.js.map
@@ -81,10 +81,13 @@ export interface WorkbenchConfig {
81
81
  /** Compilation adapter */
82
82
  adapter?: CompilationAdapter;
83
83
  /**
84
- * @deprecated Ignored at runtime. The workbench UI always renders all four
85
- * built-in panels (WXML / Console / AppData / Storage); the config no longer
86
- * filters them and never lands on the context. Kept only so existing hosts
87
- * passing it keep compiling.
84
+ * @deprecated Ignored at runtime. The config never filters the built-in
85
+ * panels and never lands on the context; which panels are on screen is
86
+ * governed solely by the persisted dock tree. A persisted tree missing part
87
+ * of the built-in debug strip is healed back to the full set on restore
88
+ * (`healMissingDebugPanels` in dock-layout.ts); the strip only disappears as
89
+ * a whole via the toolbar region toggle. Kept only so existing hosts passing
90
+ * it keep compiling.
88
91
  */
89
92
  panels?: BuiltinPanelId[];
90
93
  /** Absolute path to a custom preload script (overrides built-in simulator.js) */
@@ -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-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){if(!e)return null;let t=e.indexOf(`=`),n=t>=0?e.slice(0,t):e,r=t>=0?e.slice(t+1):``;return n?[decodeURIComponent(n),decodeURIComponent(r)]:null}function L(e){let t={};for(let n of e.split(`&`)){let e=I(n);e&&(t[e[0]]=e[1])}return t}function R(e){let[t,n]=(typeof e==`string`?e:``).split(`?`);return{pagePath:F(t),query:n?L(n):{}}}function z(e){let t={};return e.isTab&&(t[e.pagePath]=[e]),{stack:[e],tabStacks:t,currentTabPath:e.isTab?e.pagePath:null}}function B(e){return e.currentTabPath?{...e.tabStacks,[e.currentTabPath]:[...e.stack]}:e.tabStacks}function V(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 H(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 U(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 W(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 G(e,t,n){let r=e.stack[e.stack.length-1],i=B(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 K(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 q(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 J(e,t,n){switch(t){case`setNavigationBarTitle`:return{...e,title:typeof n.title==`string`?n.title:e.title};case`setNavigationBarColor`:return X(e,n);case`showNavigationBarLoading`:return{...e,loading:!0};case`hideNavigationBarLoading`:return{...e,loading:!1};case`hideHomeButton`:return{...e,homeButtonVisible:!1};default:return e}}var Y=[`linear`,`easeIn`,`easeOut`,`easeInOut`];function X(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:Y.includes(i)?i:`linear`}})();return{...e,textStyle:r,backgroundColor:i,colorAnimation:a}}function Z(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 Q=44,$=24,ee=44;function te({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`?Q:$),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:q(e.rootWindowConfig??{},e.appId)}),[e,t]),[{shell:v,tabBar:b},x]=(0,i.useState)(()=>({shell:z(_),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:Z(t.shell,e.bridgeId,t=>J(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 ne(e,S,x,C,t,n);break;case`navigateBack`:re(S,x,C,t,n);break;case`redirectTo`:await ie(e,S,x,C,t,n);break;case`reLaunch`:await ae(e,S,x,C,t,n);break;case`switchTab`:await oe(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=K(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:ee,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 ne(e,t,n,r,i,a){let{pagePath:o,query:s}=R(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:q(c.windowConfig,e.appId)},{next:u,effects:d}=V(t.current.shell,l);n(e=>({...e,shell:u})),r(d),a(!0,`navigateTo:ok`)}function re(e,t,n,r,i){let a=r.params.delta,o=Number.isFinite(Number(a))?Number(a):1,s=H(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 ie(e,t,n,r,i,a){let{pagePath:o,query:s}=R(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:q(c.windowConfig,e.appId)},{next:u,effects:d}=U(t.current.shell,l);n(e=>({...e,shell:u})),r(d),a(!0,`redirectTo:ok`)}async function ae(e,t,n,r,i,a){let{pagePath:o,query:s}=R(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:q(c.windowConfig,e.appId)},{next:u,effects:d}=W(t.current.shell,l);n(e=>({...e,shell:u})),r(d),a(!0,`reLaunch:ok`)}async function oe(e,t,n,r,i,a){let{pagePath:o}=R(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:q(t.windowConfig,e.appId)}}let{next:l,effects:u}=G(t.current.shell,o,c);n(e=>({...e,shell:l})),r(u),a(!0,`switchTab:ok`)}export{te as DeviceShell};
2
- //# sourceMappingURL=device-shell-CiLAPa0I.js.map
1
+ import{i as e,n as t,t as n}from"./jsx-runtime-BDTY6fEq.js";import{t as r}from"./bridge-channels-zhsumfky.js";var i=e(),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:e,dialog:n},r]=(0,i.useState)(()=>t.getState());return(0,i.useEffect)(()=>t.subscribe(r),[]),(0,c.jsxs)(c.Fragment,{children:[e&&(0,c.jsx)(b,{toast:e}),n?.kind===`modal`&&(0,c.jsx)(S,{dialog:n}),n?.kind===`actionSheet`&&(0,c.jsx)(C,{dialog:n})]})}function b({toast:e}){(0,i.useEffect)(()=>{if(!Number.isFinite(e.duration))return;let n=window.setTimeout(()=>t.dismissToast(e),e.duration);return()=>window.clearTimeout(n)},[e]);let n=e.icon!==`none`||!!e.image;return(0,c.jsxs)(`div`,{className:`dmui-overlay`,"aria-live":`polite`,children:[e.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:[e.image?(0,c.jsx)(`img`,{className:`dmui-toast__image`,src:e.image,alt:``}):(0,c.jsx)(x,{icon:e.icon}),e.title&&(0,c.jsx)(`div`,{className:`dmui-toast__title`,children:e.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){if(!e)return null;let t=e.indexOf(`=`),n=t>=0?e.slice(0,t):e,r=t>=0?e.slice(t+1):``;return n?[decodeURIComponent(n),decodeURIComponent(r)]:null}function L(e){let t={};for(let n of e.split(`&`)){let e=I(n);e&&(t[e[0]]=e[1])}return t}function R(e){let[t,n]=(typeof e==`string`?e:``).split(`?`);return{pagePath:F(t),query:n?L(n):{}}}function z(e){let t={};return e.isTab&&(t[e.pagePath]=[e]),{stack:[e],tabStacks:t,currentTabPath:e.isTab?e.pagePath:null}}function B(e){return e.currentTabPath?{...e.tabStacks,[e.currentTabPath]:[...e.stack]}:e.tabStacks}function V(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 H(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 U(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 W(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 G(e,t,n){let r=e.stack[e.stack.length-1],i=B(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 K(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 q(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 J(e,t,n){switch(t){case`setNavigationBarTitle`:return{...e,title:typeof n.title==`string`?n.title:e.title};case`setNavigationBarColor`:return X(e,n);case`showNavigationBarLoading`:return{...e,loading:!0};case`hideNavigationBarLoading`:return{...e,loading:!1};case`hideHomeButton`:return{...e,homeButtonVisible:!1};default:return e}}var Y=[`linear`,`easeIn`,`easeOut`,`easeInOut`];function X(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:Y.includes(i)?i:`linear`}})();return{...e,textStyle:r,backgroundColor:i,colorAnimation:a}}function Z(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 Q=44,$=24,ee=44;function te({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`?Q:$),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:q(e.rootWindowConfig??{},e.appId)}),[e,t]),[{shell:v,tabBar:b},x]=(0,i.useState)(()=>({shell:z(_),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:Z(t.shell,e.bridgeId,t=>J(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 ne(e,S,x,C,t,n);break;case`navigateBack`:re(S,x,C,t,n);break;case`redirectTo`:await ie(e,S,x,C,t,n);break;case`reLaunch`:await ae(e,S,x,C,t,n);break;case`switchTab`:await oe(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=K(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:ee,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 ne(e,t,n,r,i,a){let{pagePath:o,query:s}=R(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:q(c.windowConfig,e.appId)},{next:u,effects:d}=V(t.current.shell,l);n(e=>({...e,shell:u})),r(d),a(!0,`navigateTo:ok`)}function re(e,t,n,r,i){let a=r.params.delta,o=Number.isFinite(Number(a))?Number(a):1,s=H(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 ie(e,t,n,r,i,a){let{pagePath:o,query:s}=R(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:q(c.windowConfig,e.appId)},{next:u,effects:d}=U(t.current.shell,l);n(e=>({...e,shell:u})),r(d),a(!0,`redirectTo:ok`)}async function ae(e,t,n,r,i,a){let{pagePath:o,query:s}=R(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:q(c.windowConfig,e.appId)},{next:u,effects:d}=W(t.current.shell,l);n(e=>({...e,shell:u})),r(d),a(!0,`reLaunch:ok`)}async function oe(e,t,n,r,i,a){let{pagePath:o}=R(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:q(t.windowConfig,e.appId)}}let{next:l,effects:u}=G(t.current.shell,o,c);n(e=>({...e,shell:l})),r(u),a(!0,`switchTab:ok`)}export{te as DeviceShell};
2
+ //# sourceMappingURL=device-shell-C-wcFq3Z.js.map