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

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 (50) hide show
  1. package/dist/main/app/app.js +5 -25
  2. package/dist/main/app/native-overview.d.ts +27 -0
  3. package/dist/main/app/native-overview.js +44 -0
  4. package/dist/main/index.bundle.js +826 -690
  5. package/dist/main/ipc/bridge-router.js +180 -141
  6. package/dist/main/ipc/project-fs.js +39 -21
  7. package/dist/main/services/automation/handlers/app.js +143 -109
  8. package/dist/main/services/mcp/tools/simulator-tools.js +118 -97
  9. package/dist/main/services/network-forward/dispatch-batch.d.ts +22 -0
  10. package/dist/main/services/network-forward/dispatch-batch.js +21 -0
  11. package/dist/main/services/network-forward/index.js +5 -20
  12. package/dist/main/services/projects/create-project-service.js +54 -34
  13. package/dist/main/services/projects/types.d.ts +1 -32
  14. package/dist/main/services/service-console/console-api.js +36 -27
  15. package/dist/main/services/simulator-temp-files/disk.js +109 -86
  16. package/dist/main/services/workbench-coi-server.js +58 -45
  17. package/dist/main/utils/logger.d.ts +5 -12
  18. package/dist/main/utils/logger.js +5 -45
  19. package/dist/preload/instrumentation/wxml-extract.js +94 -62
  20. package/dist/preload/runtime/main-api-runner.d.ts +1 -1
  21. package/dist/preload/windows/main.cjs +284 -565
  22. package/dist/preload/windows/main.cjs.map +2 -2
  23. package/dist/preload/windows/simulator.cjs +37 -39
  24. package/dist/preload/windows/simulator.cjs.map +2 -2
  25. package/dist/preload/windows/simulator.js +37 -39
  26. package/dist/render-host/render-inspect.js +63 -52
  27. package/dist/renderer/assets/index-D-ksyN1p.js +49 -0
  28. package/dist/renderer/assets/workbenchSettings-COhuFF-i.js +8 -0
  29. package/dist/renderer/entries/main/index.html +1 -1
  30. package/dist/renderer/entries/workbench-settings/index.html +1 -1
  31. package/dist/shared/appdata-accumulator.js +53 -48
  32. package/dist/shared/open-in-editor-resource-path.d.ts +56 -0
  33. package/dist/shared/open-in-editor-resource-path.js +133 -0
  34. package/dist/shared/open-in-editor.d.ts +2 -9
  35. package/dist/shared/open-in-editor.js +8 -93
  36. package/dist/shared/types.d.ts +13 -0
  37. package/dist/simulator/assets/{device-shell-CUl0ILfn.js → device-shell-CiLAPa0I.js} +2 -2
  38. package/dist/simulator/assets/simulator-Dvnxry3y.js +10 -0
  39. package/dist/simulator/simulator.html +1 -1
  40. package/dist/vscode-workbench/assets/__vite-browser-external-CXi6Kz9W.js +1 -0
  41. package/dist/vscode-workbench/assets/{dist-CS7SQP3K.js → dist-TpGpmMGi.js} +3 -3
  42. package/dist/vscode-workbench/assets/{iconv-lite-umd-D3q-1-o6.js → iconv-lite-umd-C9tiCAJa.js} +1 -1
  43. package/dist/vscode-workbench/assets/{index-zjigpZ25.js → index-DJ1HyMZ7.js} +20 -22
  44. package/dist/vscode-workbench/assets/{jschardet-Cu4ufeHq.js → jschardet-DE1jV513.js} +1 -1
  45. package/dist/vscode-workbench/index.html +1 -1
  46. package/package.json +5 -5
  47. package/dist/renderer/assets/index-B-Dqb7G0.js +0 -49
  48. package/dist/renderer/assets/workbenchSettings-Bim9ol9R.js +0 -8
  49. package/dist/simulator/assets/simulator-Dz8iGcgy.js +0 -10
  50. package/dist/vscode-workbench/assets/__vite-browser-external-B0DTNerG.js +0 -1
@@ -13,6 +13,54 @@
13
13
  * through bridge-router (SERVICE_PUBLISH). Both feed this one accumulator so the
14
14
  * decode/merge/page-only/init-gate policy can't drift between modes.
15
15
  */
16
+ /** Parse a service/worker message payload; a non-string is passed through as-is. */
17
+ function parseMessagePayload(message) {
18
+ if (typeof message !== 'string')
19
+ return message;
20
+ try {
21
+ return JSON.parse(message);
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ }
27
+ /**
28
+ * Decode a `ub` (update batch) body into patch entries, PAGE modules only —
29
+ * component-module updates are dropped (see `decodeWorkerMessage`).
30
+ */
31
+ function decodeUpdateBatchBody(rawBody) {
32
+ const body = rawBody;
33
+ if (!body || typeof body !== 'object')
34
+ return null;
35
+ if (typeof body.bridgeId !== 'string' || !Array.isArray(body.updates))
36
+ return null;
37
+ const out = [];
38
+ for (const u of body.updates) {
39
+ if (!u || typeof u.moduleId !== 'string')
40
+ continue;
41
+ if (!u.moduleId.startsWith('page_'))
42
+ continue;
43
+ out.push({ mode: 'patch', bridgeId: body.bridgeId, moduleId: u.moduleId, data: u.data });
44
+ }
45
+ return out.length > 0 ? out : null;
46
+ }
47
+ /** Decode a `page_*` instance-init body into its single init entry. */
48
+ function decodePageInitBody(moduleId, rawBody) {
49
+ const body = rawBody;
50
+ if (!body || typeof body !== 'object')
51
+ return null;
52
+ if (typeof body.bridgeId !== 'string' || typeof body.path !== 'string')
53
+ return null;
54
+ if (!body.data || typeof body.data !== 'object')
55
+ return null;
56
+ return [{
57
+ mode: 'init',
58
+ bridgeId: body.bridgeId,
59
+ moduleId,
60
+ componentPath: body.path,
61
+ data: body.data,
62
+ }];
63
+ }
16
64
  /**
17
65
  * Decode a service→render message into AppData entries, or null when it is not
18
66
  * AppData-relevant. Policy: surface PAGE entries only — component entries are
@@ -20,63 +68,20 @@
20
68
  * and never receive pageUnload, which would manifest as ghost tabs).
21
69
  */
22
70
  export function decodeWorkerMessage(message) {
23
- let payload = message;
24
- if (typeof payload === 'string') {
25
- try {
26
- payload = JSON.parse(payload);
27
- }
28
- catch {
29
- return null;
30
- }
31
- }
71
+ const payload = parseMessagePayload(message);
32
72
  if (!payload || typeof payload !== 'object')
33
73
  return null;
34
74
  const record = payload;
35
- if (record.type === 'ub') {
36
- const body = record.body;
37
- if (!body || typeof body !== 'object')
38
- return null;
39
- if (typeof body.bridgeId !== 'string' || !Array.isArray(body.updates))
40
- return null;
41
- const out = [];
42
- for (const u of body.updates) {
43
- if (!u || typeof u.moduleId !== 'string')
44
- continue;
45
- if (!u.moduleId.startsWith('page_'))
46
- continue;
47
- out.push({ mode: 'patch', bridgeId: body.bridgeId, moduleId: u.moduleId, data: u.data });
48
- }
49
- return out.length > 0 ? out : null;
50
- }
75
+ if (record.type === 'ub')
76
+ return decodeUpdateBatchBody(record.body);
51
77
  if (typeof record.type === 'string' && record.type.startsWith('page_')) {
52
- const body = record.body;
53
- if (!body || typeof body !== 'object')
54
- return null;
55
- if (typeof body.bridgeId !== 'string' || typeof body.path !== 'string')
56
- return null;
57
- if (!body.data || typeof body.data !== 'object')
58
- return null;
59
- return [{
60
- mode: 'init',
61
- bridgeId: body.bridgeId,
62
- moduleId: record.type,
63
- componentPath: body.path,
64
- data: body.data,
65
- }];
78
+ return decodePageInitBody(record.type, record.body);
66
79
  }
67
80
  return null;
68
81
  }
69
82
  /** main→worker direction: container signals page teardown so cache can evict. */
70
83
  export function decodeOutgoingMessage(message) {
71
- let payload = message;
72
- if (typeof payload === 'string') {
73
- try {
74
- payload = JSON.parse(payload);
75
- }
76
- catch {
77
- return null;
78
- }
79
- }
84
+ const payload = parseMessagePayload(message);
80
85
  if (!payload || typeof payload !== 'object')
81
86
  return null;
82
87
  const r = payload;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Pure DevTools-resource-URL → project-relative-path resolution for the
3
+ * "open in editor" pipeline.
4
+ *
5
+ * Every function here is `.toString()`-injected verbatim into the DevTools
6
+ * front-end realm by `buildDevtoolsProjectSourceLinksScript` (in
7
+ * `open-in-editor.ts`), alongside being called directly from the main process.
8
+ * That constrains each function to be self-contained (no closures over
9
+ * module-level state beyond calling the OTHER functions in this file, which
10
+ * the injection site also stringifies into the same scope) — no electron / DOM
11
+ * / node deps.
12
+ */
13
+ export interface ProjectSourceContext {
14
+ /** Absolute project root on disk. */
15
+ projectRoot: string;
16
+ /** Resource server base URL used by the compiled miniapp. */
17
+ resourceBaseUrl: string;
18
+ appId: string;
19
+ /** Compiler output package root (`main` for the primary package). */
20
+ outputRoot: string;
21
+ }
22
+ export declare function decodePathname(pathname: string): string;
23
+ export declare function normalizeSlashPath(value: string): string;
24
+ export declare function safeRelativePath(segments: string[]): string | null;
25
+ /**
26
+ * Taro/webpack build + runtime chunks are compiled output, not hand-written
27
+ * source. They also collide: dimina's own service runtime attributes its
28
+ * `log()` helper to a `common.js` on the SAME dev-server origin as the
29
+ * project's compiled `common.js` chunk, so the two are URL-indistinguishable
30
+ * and a dimina-core frame would otherwise open the project's chunk. Drop these
31
+ * well-known chunk basenames so a click falls through to the DevTools Sources
32
+ * panel instead of opening the wrong (or generated) file.
33
+ */
34
+ export declare function excludeBuildChunk(rel: string | null): string | null;
35
+ /**
36
+ * Real host filesystem paths use well-known absolute roots; when they are
37
+ * outside the active project they are runtime/devtools frames, not sources.
38
+ */
39
+ export declare function isOutsideKnownRoot(normalizedRaw: string): boolean;
40
+ /**
41
+ * Chromium may hand the open-resource hook a raw absolute filesystem path
42
+ * (already project-rooted). Returns `undefined` (not `null`) when the raw
43
+ * value is not under `projectRoot` at all, so the caller can distinguish "not
44
+ * this shape" from "matched, but excluded as a build chunk" (`null`).
45
+ */
46
+ export declare function resolveFilesystemRawPath(normalizedRaw: string, projectRoot: string): string | null | undefined;
47
+ export declare function parseResourceUrl(raw: string, base: URL): URL | null;
48
+ export declare function resolveFileProtocolPath(resource: URL, projectRoot: string): string | null;
49
+ export declare function resolveHttpProtocolPath(resource: URL, base: URL, context: ProjectSourceContext): string | null;
50
+ /**
51
+ * Map a resource URL/path to a project-relative POSIX path, or null when it is
52
+ * not a mappable project source (framework frame, different origin, escapes
53
+ * the project root, or an excluded build chunk).
54
+ */
55
+ export declare function projectAwareResourcePath(resourceUrl: string, context: ProjectSourceContext): string | null;
56
+ //# sourceMappingURL=open-in-editor-resource-path.d.ts.map
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Pure DevTools-resource-URL → project-relative-path resolution for the
3
+ * "open in editor" pipeline.
4
+ *
5
+ * Every function here is `.toString()`-injected verbatim into the DevTools
6
+ * front-end realm by `buildDevtoolsProjectSourceLinksScript` (in
7
+ * `open-in-editor.ts`), alongside being called directly from the main process.
8
+ * That constrains each function to be self-contained (no closures over
9
+ * module-level state beyond calling the OTHER functions in this file, which
10
+ * the injection site also stringifies into the same scope) — no electron / DOM
11
+ * / node deps.
12
+ */
13
+ export function decodePathname(pathname) {
14
+ return pathname.split('/').map((segment) => {
15
+ try {
16
+ return decodeURIComponent(segment);
17
+ }
18
+ catch {
19
+ return segment;
20
+ }
21
+ }).join('/');
22
+ }
23
+ export function normalizeSlashPath(value) {
24
+ return decodePathname(value.replace(/\\/g, '/')).replace(/\/+/g, '/');
25
+ }
26
+ export function safeRelativePath(segments) {
27
+ if (segments.length === 0 || segments.some((segment) => !segment || segment === '.' || segment === '..')) {
28
+ return null;
29
+ }
30
+ return segments.join('/');
31
+ }
32
+ /**
33
+ * Taro/webpack build + runtime chunks are compiled output, not hand-written
34
+ * source. They also collide: dimina's own service runtime attributes its
35
+ * `log()` helper to a `common.js` on the SAME dev-server origin as the
36
+ * project's compiled `common.js` chunk, so the two are URL-indistinguishable
37
+ * and a dimina-core frame would otherwise open the project's chunk. Drop these
38
+ * well-known chunk basenames so a click falls through to the DevTools Sources
39
+ * panel instead of opening the wrong (or generated) file.
40
+ */
41
+ export function excludeBuildChunk(rel) {
42
+ if (!rel)
43
+ return rel;
44
+ const baseName = rel.split('/').pop();
45
+ return baseName === 'common.js' || baseName === 'vendors.js' || baseName === 'runtime.js'
46
+ || baseName === 'taro.js' || baseName === 'babelHelpers.js'
47
+ ? null
48
+ : rel;
49
+ }
50
+ /**
51
+ * Real host filesystem paths use well-known absolute roots; when they are
52
+ * outside the active project they are runtime/devtools frames, not sources.
53
+ */
54
+ export function isOutsideKnownRoot(normalizedRaw) {
55
+ return /^\/(?:Volumes|Users|home|private|tmp|var|opt|Applications)\//.test(normalizedRaw);
56
+ }
57
+ /**
58
+ * Chromium may hand the open-resource hook a raw absolute filesystem path
59
+ * (already project-rooted). Returns `undefined` (not `null`) when the raw
60
+ * value is not under `projectRoot` at all, so the caller can distinguish "not
61
+ * this shape" from "matched, but excluded as a build chunk" (`null`).
62
+ */
63
+ export function resolveFilesystemRawPath(normalizedRaw, projectRoot) {
64
+ if (!projectRoot)
65
+ return undefined;
66
+ if (normalizedRaw !== projectRoot && !normalizedRaw.startsWith(`${projectRoot}/`))
67
+ return undefined;
68
+ const relative = normalizedRaw.slice(projectRoot.length).replace(/^\/+/, '');
69
+ return excludeBuildChunk(safeRelativePath(relative.split('/').filter(Boolean)));
70
+ }
71
+ export function parseResourceUrl(raw, base) {
72
+ try {
73
+ return raw.startsWith('/') && !raw.startsWith('//') ? new URL(raw, base.origin) : new URL(raw);
74
+ }
75
+ catch {
76
+ return null;
77
+ }
78
+ }
79
+ export function resolveFileProtocolPath(resource, projectRoot) {
80
+ const filePath = normalizeSlashPath(resource.pathname);
81
+ if (!projectRoot || (filePath !== projectRoot && !filePath.startsWith(`${projectRoot}/`)))
82
+ return null;
83
+ return excludeBuildChunk(safeRelativePath(filePath.slice(projectRoot.length).replace(/^\/+/, '').split('/').filter(Boolean)));
84
+ }
85
+ export function resolveHttpProtocolPath(resource, base, context) {
86
+ if (resource.protocol !== 'http:' && resource.protocol !== 'https:')
87
+ return null;
88
+ if (resource.origin !== base.origin)
89
+ return null;
90
+ let segments = decodePathname(resource.pathname).split('/').filter(Boolean);
91
+ if (context.appId && segments[0] === context.appId) {
92
+ segments = segments.slice(1);
93
+ if (context.outputRoot && segments[0] === context.outputRoot)
94
+ segments = segments.slice(1);
95
+ }
96
+ return excludeBuildChunk(safeRelativePath(segments));
97
+ }
98
+ /**
99
+ * Map a resource URL/path to a project-relative POSIX path, or null when it is
100
+ * not a mappable project source (framework frame, different origin, escapes
101
+ * the project root, or an excluded build chunk).
102
+ */
103
+ export function projectAwareResourcePath(resourceUrl, context) {
104
+ let base;
105
+ try {
106
+ base = new URL(context.resourceBaseUrl);
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ const projectRoot = normalizeSlashPath(context.projectRoot).replace(/\/$/, '');
112
+ const raw = resourceUrl.trim();
113
+ if (!raw)
114
+ return null;
115
+ const normalizedRaw = normalizeSlashPath(raw);
116
+ const filesystemRelative = resolveFilesystemRawPath(normalizedRaw, projectRoot);
117
+ if (filesystemRelative !== undefined)
118
+ return filesystemRelative;
119
+ if (isOutsideKnownRoot(normalizedRaw))
120
+ return null;
121
+ // Reject relative runtime labels such as `service.js` or
122
+ // `electron/js2c/renderer_init`; project source locations must be an
123
+ // absolute URL/path so they can be scoped to the active project.
124
+ if (!raw.startsWith('/') && !/^[a-z][a-z0-9+.-]*:/i.test(raw))
125
+ return null;
126
+ const resource = parseResourceUrl(raw, base);
127
+ if (!resource)
128
+ return null;
129
+ if (resource.protocol === 'file:')
130
+ return resolveFileProtocolPath(resource, projectRoot);
131
+ return resolveHttpProtocolPath(resource, base, context);
132
+ }
133
+ //# sourceMappingURL=open-in-editor-resource-path.js.map
@@ -16,6 +16,8 @@
16
16
  * node deps so it is unit-testable and shared by main + the injected front-end
17
17
  * snippet's expectations.
18
18
  */
19
+ import { type ProjectSourceContext } from './open-in-editor-resource-path.js';
20
+ export type { ProjectSourceContext } from './open-in-editor-resource-path.js';
19
21
  /**
20
22
  * Sentinel scheme for the encoded "open in editor" request. A bare custom scheme
21
23
  * (no `//authority`) keeps the encoded payload entirely in the URL's path/query,
@@ -32,15 +34,6 @@ export interface OpenInEditorRequest {
32
34
  /** 0-based column as reported by DevTools (may be undefined). */
33
35
  column?: number;
34
36
  }
35
- export interface ProjectSourceContext {
36
- /** Absolute project root on disk. */
37
- projectRoot: string;
38
- /** Resource server base URL used by the compiled miniapp. */
39
- resourceBaseUrl: string;
40
- appId: string;
41
- /** Compiler output package root (`main` for the primary package). */
42
- outputRoot: string;
43
- }
44
37
  /**
45
38
  * Encode an open-in-editor request as a sentinel URL the DevTools front-end can
46
39
  * hand to `InspectorFrontendHost.openInNewTab(...)`. All fields ride in the
@@ -16,6 +16,7 @@
16
16
  * node deps so it is unit-testable and shared by main + the injected front-end
17
17
  * snippet's expectations.
18
18
  */
19
+ import { decodePathname, excludeBuildChunk, isOutsideKnownRoot, normalizeSlashPath, parseResourceUrl, projectAwareResourcePath, resolveFileProtocolPath, resolveFilesystemRawPath, resolveHttpProtocolPath, safeRelativePath, } from './open-in-editor-resource-path.js';
19
20
  /**
20
21
  * Sentinel scheme for the encoded "open in editor" request. A bare custom scheme
21
22
  * (no `//authority`) keeps the encoded payload entirely in the URL's path/query,
@@ -138,98 +139,6 @@ export function resourceUrlToProjectRelativePath(resourceUrl, expectedOriginOrCo
138
139
  return null;
139
140
  return segments.slice(1).join('/');
140
141
  }
141
- function decodePathname(pathname) {
142
- return pathname.split('/').map((segment) => {
143
- try {
144
- return decodeURIComponent(segment);
145
- }
146
- catch {
147
- return segment;
148
- }
149
- }).join('/');
150
- }
151
- function normalizeSlashPath(value) {
152
- return decodePathname(value.replace(/\\/g, '/')).replace(/\/+/g, '/');
153
- }
154
- function safeRelativePath(segments) {
155
- if (segments.length === 0 || segments.some((segment) => !segment || segment === '.' || segment === '..')) {
156
- return null;
157
- }
158
- return segments.join('/');
159
- }
160
- function projectAwareResourcePath(resourceUrl, context) {
161
- let base;
162
- try {
163
- base = new URL(context.resourceBaseUrl);
164
- }
165
- catch {
166
- return null;
167
- }
168
- const projectRoot = normalizeSlashPath(context.projectRoot).replace(/\/$/, '');
169
- const raw = resourceUrl.trim();
170
- if (!raw)
171
- return null;
172
- // Taro/webpack build + runtime chunks are compiled output, not hand-written
173
- // source. They also collide: dimina's own service runtime attributes its
174
- // `log()` helper to a `common.js` on the SAME dev-server origin as the
175
- // project's compiled `common.js` chunk, so the two are URL-indistinguishable
176
- // and a dimina-core frame would otherwise open the project's chunk. Drop these
177
- // well-known chunk basenames so a click falls through to the DevTools Sources
178
- // panel instead of opening the wrong (or generated) file. Inlined (not a module
179
- // const) because this function is `.toString()`-injected into the DevTools realm.
180
- const excludeBuildChunk = (rel) => {
181
- if (!rel)
182
- return rel;
183
- const base = rel.split('/').pop();
184
- return base === 'common.js' || base === 'vendors.js' || base === 'runtime.js'
185
- || base === 'taro.js' || base === 'babelHelpers.js'
186
- ? null
187
- : rel;
188
- };
189
- // Chromium may hand the open-resource hook a raw absolute filesystem path.
190
- const normalizedRaw = normalizeSlashPath(raw);
191
- if (projectRoot && (normalizedRaw === projectRoot || normalizedRaw.startsWith(`${projectRoot}/`))) {
192
- const relative = normalizedRaw.slice(projectRoot.length).replace(/^\/+/, '');
193
- return excludeBuildChunk(safeRelativePath(relative.split('/').filter(Boolean)));
194
- }
195
- // Sourcemap sources commonly use virtual root paths such as `/pages/x.js`.
196
- // Real host filesystem paths use well-known absolute roots; when they are
197
- // outside the active project they are runtime/devtools frames, not sources.
198
- if (/^\/(?:Volumes|Users|home|private|tmp|var|opt|Applications)\//.test(normalizedRaw)) {
199
- return null;
200
- }
201
- // Reject relative runtime labels such as `service.js` or
202
- // `electron/js2c/renderer_init`; project source locations must be an
203
- // absolute URL/path so they can be scoped to the active project.
204
- if (!raw.startsWith('/') && !/^[a-z][a-z0-9+.-]*:/i.test(raw))
205
- return null;
206
- let resource;
207
- try {
208
- resource = raw.startsWith('/') && !raw.startsWith('//')
209
- ? new URL(raw, base.origin)
210
- : new URL(raw);
211
- }
212
- catch {
213
- return null;
214
- }
215
- if (resource.protocol === 'file:') {
216
- const filePath = normalizeSlashPath(resource.pathname);
217
- if (!projectRoot || (filePath !== projectRoot && !filePath.startsWith(`${projectRoot}/`)))
218
- return null;
219
- return excludeBuildChunk(safeRelativePath(filePath.slice(projectRoot.length).replace(/^\/+/, '').split('/').filter(Boolean)));
220
- }
221
- if (resource.protocol !== 'http:' && resource.protocol !== 'https:')
222
- return null;
223
- if (resource.origin !== base.origin)
224
- return null;
225
- let segments = decodePathname(resource.pathname).split('/').filter(Boolean);
226
- if (context.appId && segments[0] === context.appId) {
227
- segments = segments.slice(1);
228
- if (context.outputRoot && segments[0] === context.outputRoot)
229
- segments = segments.slice(1);
230
- }
231
- return excludeBuildChunk(safeRelativePath(segments));
232
- }
233
142
  /** Read the project/source routing metadata carried by a service-host spawn URL. */
234
143
  export function projectSourceContextFromServiceHostUrl(serviceHostUrl, activeProjectRoot) {
235
144
  let url;
@@ -286,10 +195,16 @@ export function buildDevtoolsProjectSourceLinksScript(context) {
286
195
  }
287
196
 
288
197
  const cfg = ${config}
289
- const diminaProjectSourcePath = ${projectAwareResourcePath.toString()}
290
198
  const decodePathname = ${decodePathname.toString()}
291
199
  const normalizeSlashPath = ${normalizeSlashPath.toString()}
292
200
  const safeRelativePath = ${safeRelativePath.toString()}
201
+ const excludeBuildChunk = ${excludeBuildChunk.toString()}
202
+ const isOutsideKnownRoot = ${isOutsideKnownRoot.toString()}
203
+ const resolveFilesystemRawPath = ${resolveFilesystemRawPath.toString()}
204
+ const parseResourceUrl = ${parseResourceUrl.toString()}
205
+ const resolveFileProtocolPath = ${resolveFileProtocolPath.toString()}
206
+ const resolveHttpProtocolPath = ${resolveHttpProtocolPath.toString()}
207
+ const diminaProjectSourcePath = ${projectAwareResourcePath.toString()}
293
208
  const observedRoots = new Set()
294
209
  const observers = []
295
210
  const clickBindings = []
@@ -199,19 +199,32 @@ export interface ProjectsProvider {
199
199
  getCompileConfig?(dirPath: string): unknown;
200
200
  saveCompileConfig?(dirPath: string, cfg: unknown): void | Promise<void>;
201
201
  }
202
+ /**
203
+ * A template the user can pick from in the "新建项目" dialog. Exactly one of
204
+ * `source` or `generate` should be supplied; if both are omitted, the
205
+ * service refuses to materialise the template.
206
+ */
202
207
  export interface ProjectTemplate {
208
+ /** Stable identifier. Used by host whitelists and the `templateId` field of CreateProjectInput. */
203
209
  id: string;
210
+ /** Human-readable label shown in the dialog. */
204
211
  name: string;
205
212
  description?: string;
206
213
  icon?: string;
214
+ /** Copy-tree source. `path` must be absolute. */
207
215
  source?: {
208
216
  type: 'directory';
209
217
  path: string;
210
218
  };
219
+ /** Programmatic generator. `target` is the absolute destination directory. */
211
220
  generate?: (target: string, opts: {
212
221
  name: string;
213
222
  }) => Promise<void>;
214
223
  }
224
+ /**
225
+ * Payload returned from the create-project dialog. The service uses this to
226
+ * scaffold disk content and to register the project with the provider.
227
+ */
215
228
  export interface CreateProjectInput {
216
229
  name: string;
217
230
  path: string;
@@ -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){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
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