@monimesl/dot-simulator 0.1.0-alpha.2 → 0.1.0-alpha.4
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.
- package/dist/client/service-bridge.js +486 -48
- package/dist/client/service-bridge.js.map +1 -1
- package/dist/client/simulator.js +633 -62
- package/dist/client/simulator.js.map +1 -1
- package/dist/client/webview-bridge.js +12 -0
- package/dist/client/webview-bridge.js.map +1 -1
- package/dist/node/index.d.ts +18 -3
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +702 -14
- package/dist/node/index.js.map +1 -1
- package/package.json +3 -3
package/dist/client/simulator.js
CHANGED
|
@@ -15,72 +15,498 @@
|
|
|
15
15
|
}
|
|
16
16
|
return registry;
|
|
17
17
|
}
|
|
18
|
+
const AmountInput = defineComponent({
|
|
19
|
+
name: "AmountInput",
|
|
20
|
+
props: {
|
|
21
|
+
value: "number",
|
|
22
|
+
currency: "string",
|
|
23
|
+
decimals: "number",
|
|
24
|
+
label: "string",
|
|
25
|
+
placeholder: "string",
|
|
26
|
+
hint: "string",
|
|
27
|
+
error: "string",
|
|
28
|
+
disabled: "boolean"
|
|
29
|
+
},
|
|
30
|
+
events: ["change"],
|
|
31
|
+
children: "none"
|
|
32
|
+
});
|
|
33
|
+
const Button = defineComponent({
|
|
34
|
+
name: "Button",
|
|
35
|
+
props: {
|
|
36
|
+
variant: ["primary", "secondary"],
|
|
37
|
+
disabled: "boolean",
|
|
38
|
+
loading: "boolean"
|
|
39
|
+
},
|
|
40
|
+
events: ["click"],
|
|
41
|
+
children: "text"
|
|
42
|
+
});
|
|
43
|
+
const SIZES = [
|
|
44
|
+
"small",
|
|
45
|
+
"medium",
|
|
46
|
+
"large"
|
|
47
|
+
];
|
|
48
|
+
const SPACES = [
|
|
49
|
+
"none",
|
|
50
|
+
"small",
|
|
51
|
+
"medium",
|
|
52
|
+
"large"
|
|
53
|
+
];
|
|
54
|
+
const TONES = [
|
|
55
|
+
"default",
|
|
56
|
+
"muted",
|
|
57
|
+
"info",
|
|
58
|
+
"success",
|
|
59
|
+
"warning",
|
|
60
|
+
"danger"
|
|
61
|
+
];
|
|
62
|
+
const STATUS_TONES = [
|
|
63
|
+
"default",
|
|
64
|
+
"info",
|
|
65
|
+
"success",
|
|
66
|
+
"warning",
|
|
67
|
+
"danger"
|
|
68
|
+
];
|
|
69
|
+
const ICON_NAMES = [
|
|
70
|
+
"arrow-down",
|
|
71
|
+
"arrow-left",
|
|
72
|
+
"arrow-right",
|
|
73
|
+
"arrow-up",
|
|
74
|
+
"bank",
|
|
75
|
+
"bell",
|
|
76
|
+
"bolt",
|
|
77
|
+
"calendar",
|
|
78
|
+
"card",
|
|
79
|
+
"cart",
|
|
80
|
+
"cash",
|
|
81
|
+
"check",
|
|
82
|
+
"chevron-down",
|
|
83
|
+
"chevron-left",
|
|
84
|
+
"chevron-right",
|
|
85
|
+
"chevron-up",
|
|
86
|
+
"clock",
|
|
87
|
+
"close",
|
|
88
|
+
"copy",
|
|
89
|
+
"download",
|
|
90
|
+
"edit",
|
|
91
|
+
"error",
|
|
92
|
+
"eye",
|
|
93
|
+
"eye-off",
|
|
94
|
+
"file",
|
|
95
|
+
"gift",
|
|
96
|
+
"grid",
|
|
97
|
+
"heart",
|
|
98
|
+
"help",
|
|
99
|
+
"history",
|
|
100
|
+
"home",
|
|
101
|
+
"image",
|
|
102
|
+
"info",
|
|
103
|
+
"list",
|
|
104
|
+
"location",
|
|
105
|
+
"lock",
|
|
106
|
+
"logout",
|
|
107
|
+
"mail",
|
|
108
|
+
"minus",
|
|
109
|
+
"mobile",
|
|
110
|
+
"more",
|
|
111
|
+
"phone",
|
|
112
|
+
"plus",
|
|
113
|
+
"qr-code",
|
|
114
|
+
"receipt",
|
|
115
|
+
"refresh",
|
|
116
|
+
"search",
|
|
117
|
+
"send",
|
|
118
|
+
"settings",
|
|
119
|
+
"share",
|
|
120
|
+
"star",
|
|
121
|
+
"success",
|
|
122
|
+
"trash",
|
|
123
|
+
"upload",
|
|
124
|
+
"user",
|
|
125
|
+
"users",
|
|
126
|
+
"wallet",
|
|
127
|
+
"warning",
|
|
128
|
+
"water",
|
|
129
|
+
"wifi"
|
|
130
|
+
];
|
|
131
|
+
const Carousel = defineComponent({
|
|
132
|
+
name: "Carousel",
|
|
133
|
+
props: {
|
|
134
|
+
autoplay: "boolean",
|
|
135
|
+
interval: "number",
|
|
136
|
+
loop: "boolean",
|
|
137
|
+
indicator: ["dots", "none"],
|
|
138
|
+
gap: SPACES,
|
|
139
|
+
effect: ["slide", "scale"],
|
|
140
|
+
index: "number"
|
|
141
|
+
},
|
|
142
|
+
events: ["change"],
|
|
143
|
+
children: "elements"
|
|
144
|
+
});
|
|
145
|
+
const Chip = defineComponent({
|
|
146
|
+
name: "Chip",
|
|
147
|
+
props: {
|
|
148
|
+
label: "string",
|
|
149
|
+
icon: ICON_NAMES,
|
|
150
|
+
selected: "boolean",
|
|
151
|
+
disabled: "boolean"
|
|
152
|
+
},
|
|
153
|
+
events: ["tap"],
|
|
154
|
+
children: "none"
|
|
155
|
+
});
|
|
156
|
+
const CodeInput = defineComponent({
|
|
157
|
+
name: "CodeInput",
|
|
158
|
+
props: {
|
|
159
|
+
value: "string",
|
|
160
|
+
length: "number",
|
|
161
|
+
label: "string",
|
|
162
|
+
hint: "string",
|
|
163
|
+
error: "string",
|
|
164
|
+
secure: "boolean",
|
|
165
|
+
disabled: "boolean"
|
|
166
|
+
},
|
|
167
|
+
events: ["change", "complete"],
|
|
168
|
+
children: "none"
|
|
169
|
+
});
|
|
170
|
+
const Divider = defineComponent({
|
|
171
|
+
name: "Divider",
|
|
172
|
+
children: "none"
|
|
173
|
+
});
|
|
174
|
+
const EmptyState = defineComponent({
|
|
175
|
+
name: "EmptyState",
|
|
176
|
+
props: {
|
|
177
|
+
icon: ICON_NAMES,
|
|
178
|
+
title: "string",
|
|
179
|
+
text: "string"
|
|
180
|
+
},
|
|
181
|
+
children: "elements"
|
|
182
|
+
});
|
|
183
|
+
const Spinner = defineComponent({
|
|
184
|
+
name: "Spinner",
|
|
185
|
+
props: { size: SIZES },
|
|
186
|
+
children: "none"
|
|
187
|
+
});
|
|
188
|
+
const ProgressBar = defineComponent({
|
|
189
|
+
name: "ProgressBar",
|
|
190
|
+
props: { value: "number" },
|
|
191
|
+
children: "none"
|
|
192
|
+
});
|
|
193
|
+
const Notice = defineComponent({
|
|
194
|
+
name: "Notice",
|
|
195
|
+
props: {
|
|
196
|
+
tone: STATUS_TONES,
|
|
197
|
+
title: "string"
|
|
198
|
+
},
|
|
199
|
+
children: "text"
|
|
200
|
+
});
|
|
201
|
+
const Badge = defineComponent({
|
|
202
|
+
name: "Badge",
|
|
203
|
+
props: { tone: STATUS_TONES },
|
|
204
|
+
children: "text"
|
|
205
|
+
});
|
|
206
|
+
const Footer = defineComponent({
|
|
207
|
+
name: "Footer",
|
|
208
|
+
children: "elements"
|
|
209
|
+
});
|
|
210
|
+
const Grid = defineComponent({
|
|
211
|
+
name: "Grid",
|
|
212
|
+
props: {
|
|
213
|
+
columns: "number",
|
|
214
|
+
gap: SPACES
|
|
215
|
+
},
|
|
216
|
+
children: "elements"
|
|
217
|
+
});
|
|
218
|
+
const GridItem = defineComponent({
|
|
219
|
+
name: "GridItem",
|
|
220
|
+
props: {
|
|
221
|
+
label: "string",
|
|
222
|
+
icon: ICON_NAMES,
|
|
223
|
+
image: "string",
|
|
224
|
+
badge: "string"
|
|
225
|
+
},
|
|
226
|
+
events: ["tap"],
|
|
227
|
+
children: "none"
|
|
228
|
+
});
|
|
229
|
+
const Icon = defineComponent({
|
|
230
|
+
name: "Icon",
|
|
231
|
+
props: {
|
|
232
|
+
name: ICON_NAMES,
|
|
233
|
+
size: SIZES,
|
|
234
|
+
tone: TONES
|
|
235
|
+
},
|
|
236
|
+
children: "none",
|
|
237
|
+
inline: true
|
|
238
|
+
});
|
|
239
|
+
const Image = defineComponent({
|
|
240
|
+
name: "Image",
|
|
241
|
+
props: {
|
|
242
|
+
src: "string",
|
|
243
|
+
alt: "string",
|
|
244
|
+
width: "number",
|
|
245
|
+
height: "number",
|
|
246
|
+
fit: ["cover", "contain"],
|
|
247
|
+
shape: [
|
|
248
|
+
"rounded",
|
|
249
|
+
"square",
|
|
250
|
+
"circle"
|
|
251
|
+
]
|
|
252
|
+
},
|
|
253
|
+
events: ["load", "error"],
|
|
254
|
+
children: "none"
|
|
255
|
+
});
|
|
256
|
+
const Input = defineComponent({
|
|
257
|
+
name: "Input",
|
|
258
|
+
props: {
|
|
259
|
+
value: "string",
|
|
260
|
+
placeholder: "string",
|
|
261
|
+
label: "string",
|
|
262
|
+
hint: "string",
|
|
263
|
+
error: "string",
|
|
264
|
+
prefix: "string",
|
|
265
|
+
suffix: "string",
|
|
266
|
+
type: [
|
|
267
|
+
"text",
|
|
268
|
+
"number",
|
|
269
|
+
"email",
|
|
270
|
+
"phone",
|
|
271
|
+
"password"
|
|
272
|
+
],
|
|
273
|
+
maxLength: "number",
|
|
274
|
+
disabled: "boolean"
|
|
275
|
+
},
|
|
276
|
+
events: ["change", "submit"],
|
|
277
|
+
children: "none"
|
|
278
|
+
});
|
|
279
|
+
const List = defineComponent({
|
|
280
|
+
name: "List",
|
|
281
|
+
children: "elements"
|
|
282
|
+
});
|
|
283
|
+
const ListItem = defineComponent({
|
|
284
|
+
name: "ListItem",
|
|
285
|
+
props: {
|
|
286
|
+
title: "string",
|
|
287
|
+
subtitle: "string",
|
|
288
|
+
value: "string",
|
|
289
|
+
icon: ICON_NAMES,
|
|
290
|
+
image: "string"
|
|
291
|
+
},
|
|
292
|
+
events: ["tap"],
|
|
293
|
+
children: "elements"
|
|
294
|
+
});
|
|
295
|
+
const Sheet = defineComponent({
|
|
296
|
+
name: "Sheet",
|
|
297
|
+
props: {
|
|
298
|
+
open: "boolean",
|
|
299
|
+
title: "string"
|
|
300
|
+
},
|
|
301
|
+
events: ["close"],
|
|
302
|
+
children: "elements"
|
|
303
|
+
});
|
|
304
|
+
const Toast = defineComponent({
|
|
305
|
+
name: "Toast",
|
|
306
|
+
props: {
|
|
307
|
+
message: "string",
|
|
308
|
+
tone: STATUS_TONES,
|
|
309
|
+
duration: "number"
|
|
310
|
+
},
|
|
311
|
+
events: ["hide"],
|
|
312
|
+
children: "none"
|
|
313
|
+
});
|
|
314
|
+
const QRCode = defineComponent({
|
|
315
|
+
name: "QRCode",
|
|
316
|
+
props: {
|
|
317
|
+
value: "string",
|
|
318
|
+
size: "number",
|
|
319
|
+
label: "string"
|
|
320
|
+
},
|
|
321
|
+
children: "none"
|
|
322
|
+
});
|
|
323
|
+
const Select = defineComponent({
|
|
324
|
+
name: "Select",
|
|
325
|
+
props: {
|
|
326
|
+
value: "string",
|
|
327
|
+
label: "string",
|
|
328
|
+
placeholder: "string",
|
|
329
|
+
hint: "string",
|
|
330
|
+
error: "string",
|
|
331
|
+
disabled: "boolean"
|
|
332
|
+
},
|
|
333
|
+
events: ["change"],
|
|
334
|
+
children: "elements"
|
|
335
|
+
});
|
|
336
|
+
const Option = defineComponent({
|
|
337
|
+
name: "Option",
|
|
338
|
+
props: {
|
|
339
|
+
value: "string",
|
|
340
|
+
label: "string"
|
|
341
|
+
},
|
|
342
|
+
children: "none"
|
|
343
|
+
});
|
|
344
|
+
const Skeleton = defineComponent({
|
|
345
|
+
name: "Skeleton",
|
|
346
|
+
props: {
|
|
347
|
+
shape: [
|
|
348
|
+
"text",
|
|
349
|
+
"circle",
|
|
350
|
+
"box"
|
|
351
|
+
],
|
|
352
|
+
lines: "number",
|
|
353
|
+
height: "number"
|
|
354
|
+
},
|
|
355
|
+
children: "none"
|
|
356
|
+
});
|
|
357
|
+
const Tabs = defineComponent({
|
|
358
|
+
name: "Tabs",
|
|
359
|
+
props: {
|
|
360
|
+
value: "string",
|
|
361
|
+
variant: ["underline", "segmented"]
|
|
362
|
+
},
|
|
363
|
+
events: ["change"],
|
|
364
|
+
children: "elements"
|
|
365
|
+
});
|
|
366
|
+
const Tab = defineComponent({
|
|
367
|
+
name: "Tab",
|
|
368
|
+
props: {
|
|
369
|
+
value: "string",
|
|
370
|
+
label: "string",
|
|
371
|
+
badge: "number"
|
|
372
|
+
},
|
|
373
|
+
children: "none"
|
|
374
|
+
});
|
|
375
|
+
const Text = defineComponent({
|
|
376
|
+
name: "Text",
|
|
377
|
+
props: {
|
|
378
|
+
variant: [
|
|
379
|
+
"title",
|
|
380
|
+
"body",
|
|
381
|
+
"caption"
|
|
382
|
+
],
|
|
383
|
+
tone: TONES,
|
|
384
|
+
weight: [
|
|
385
|
+
"regular",
|
|
386
|
+
"medium",
|
|
387
|
+
"bold"
|
|
388
|
+
],
|
|
389
|
+
align: [
|
|
390
|
+
"start",
|
|
391
|
+
"center",
|
|
392
|
+
"end"
|
|
393
|
+
],
|
|
394
|
+
maxLines: "number"
|
|
395
|
+
},
|
|
396
|
+
children: "text",
|
|
397
|
+
inline: true
|
|
398
|
+
});
|
|
399
|
+
const TextArea = defineComponent({
|
|
400
|
+
name: "TextArea",
|
|
401
|
+
props: {
|
|
402
|
+
value: "string",
|
|
403
|
+
placeholder: "string",
|
|
404
|
+
label: "string",
|
|
405
|
+
hint: "string",
|
|
406
|
+
error: "string",
|
|
407
|
+
rows: "number",
|
|
408
|
+
maxLength: "number",
|
|
409
|
+
disabled: "boolean"
|
|
410
|
+
},
|
|
411
|
+
events: ["change"],
|
|
412
|
+
children: "none"
|
|
413
|
+
});
|
|
414
|
+
const Switch = defineComponent({
|
|
415
|
+
name: "Switch",
|
|
416
|
+
props: {
|
|
417
|
+
checked: "boolean",
|
|
418
|
+
label: "string",
|
|
419
|
+
disabled: "boolean"
|
|
420
|
+
},
|
|
421
|
+
events: ["change"],
|
|
422
|
+
children: "none"
|
|
423
|
+
});
|
|
424
|
+
const Checkbox = defineComponent({
|
|
425
|
+
name: "Checkbox",
|
|
426
|
+
props: {
|
|
427
|
+
checked: "boolean",
|
|
428
|
+
label: "string",
|
|
429
|
+
disabled: "boolean"
|
|
430
|
+
},
|
|
431
|
+
events: ["change"],
|
|
432
|
+
children: "none"
|
|
433
|
+
});
|
|
434
|
+
const RadioGroup = defineComponent({
|
|
435
|
+
name: "RadioGroup",
|
|
436
|
+
props: {
|
|
437
|
+
value: "string",
|
|
438
|
+
label: "string",
|
|
439
|
+
disabled: "boolean"
|
|
440
|
+
},
|
|
441
|
+
events: ["change"],
|
|
442
|
+
children: "elements"
|
|
443
|
+
});
|
|
18
444
|
const builtinComponents = {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
445
|
+
AmountInput,
|
|
446
|
+
Badge,
|
|
447
|
+
Button,
|
|
448
|
+
Carousel,
|
|
449
|
+
Checkbox,
|
|
450
|
+
Chip,
|
|
451
|
+
CodeInput,
|
|
452
|
+
Divider,
|
|
453
|
+
EmptyState,
|
|
454
|
+
Footer,
|
|
455
|
+
Grid,
|
|
456
|
+
GridItem,
|
|
457
|
+
Icon,
|
|
458
|
+
Image,
|
|
459
|
+
Input,
|
|
460
|
+
List,
|
|
461
|
+
ListItem,
|
|
462
|
+
Notice,
|
|
463
|
+
Option,
|
|
464
|
+
ProgressBar,
|
|
465
|
+
QRCode,
|
|
466
|
+
Radio: defineComponent({
|
|
467
|
+
name: "Radio",
|
|
41
468
|
props: {
|
|
42
469
|
value: "string",
|
|
43
|
-
placeholder: "string",
|
|
44
470
|
label: "string",
|
|
45
|
-
type: [
|
|
46
|
-
"text",
|
|
47
|
-
"number",
|
|
48
|
-
"email",
|
|
49
|
-
"phone",
|
|
50
|
-
"password"
|
|
51
|
-
],
|
|
52
|
-
maxLength: "number",
|
|
53
471
|
disabled: "boolean"
|
|
54
472
|
},
|
|
55
|
-
events: ["change", "submit"],
|
|
56
473
|
children: "none"
|
|
57
474
|
}),
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
475
|
+
RadioGroup,
|
|
476
|
+
Select,
|
|
477
|
+
Sheet,
|
|
478
|
+
Skeleton,
|
|
479
|
+
Spinner,
|
|
480
|
+
Switch,
|
|
481
|
+
Tab,
|
|
482
|
+
Tabs,
|
|
483
|
+
Text,
|
|
484
|
+
TextArea,
|
|
485
|
+
Toast,
|
|
68
486
|
View: defineComponent({
|
|
69
487
|
name: "View",
|
|
70
488
|
props: {
|
|
489
|
+
gap: SPACES,
|
|
71
490
|
direction: ["column", "row"],
|
|
72
|
-
gap: [
|
|
73
|
-
"none",
|
|
74
|
-
"small",
|
|
75
|
-
"medium",
|
|
76
|
-
"large"
|
|
77
|
-
],
|
|
78
491
|
align: [
|
|
79
492
|
"stretch",
|
|
80
493
|
"start",
|
|
81
494
|
"center",
|
|
82
495
|
"end"
|
|
83
496
|
],
|
|
497
|
+
justify: [
|
|
498
|
+
"start",
|
|
499
|
+
"center",
|
|
500
|
+
"end",
|
|
501
|
+
"between"
|
|
502
|
+
],
|
|
503
|
+
wrap: "boolean",
|
|
504
|
+
grow: "boolean",
|
|
505
|
+
padding: SPACES,
|
|
506
|
+
paddingTop: SPACES,
|
|
507
|
+
paddingStart: SPACES,
|
|
508
|
+
paddingEnd: SPACES,
|
|
509
|
+
paddingBottom: SPACES,
|
|
84
510
|
variant: ["plain", "card"]
|
|
85
511
|
},
|
|
86
512
|
events: ["tap"],
|
|
@@ -96,6 +522,8 @@
|
|
|
96
522
|
this.code = code;
|
|
97
523
|
}
|
|
98
524
|
};
|
|
525
|
+
const LABEL = "[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?";
|
|
526
|
+
new RegExp(`^(?:\\*\\.${LABEL}(?:\\.${LABEL})+|${LABEL}(?:\\.${LABEL})*)$`);
|
|
99
527
|
const SEMVER_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
|
100
528
|
function majorVersion(version) {
|
|
101
529
|
return parseVersion(version).major;
|
|
@@ -337,7 +765,7 @@
|
|
|
337
765
|
};
|
|
338
766
|
//#endregion
|
|
339
767
|
//#region src/host.ts
|
|
340
|
-
function startHost({ logic, ui, manifest, dashVersion, minRuntimeVersion, systemContext, handlers = {}, askPermission, observe }) {
|
|
768
|
+
function startHost({ logic, ui, manifest, dashVersion, minRuntimeVersion, systemContext, handlers = {}, askPermission, observe, restorePages = [], onBarsChange }) {
|
|
341
769
|
checkCompatibility(manifest, {
|
|
342
770
|
dashVersion,
|
|
343
771
|
minRuntimeVersion
|
|
@@ -357,6 +785,18 @@
|
|
|
357
785
|
ui.post(message);
|
|
358
786
|
logic.post(message);
|
|
359
787
|
};
|
|
788
|
+
const barsByInstance = /* @__PURE__ */ new Map();
|
|
789
|
+
const showBars = () => {
|
|
790
|
+
const top = stack.top;
|
|
791
|
+
const bars = top && barsByInstance.get(top.instanceId);
|
|
792
|
+
onBarsChange?.({
|
|
793
|
+
title: bars?.navigationBar.title ?? manifest.name,
|
|
794
|
+
navigationBarHidden: bars?.navigationBar.hidden ?? false,
|
|
795
|
+
navigationBarColor: bars?.navigationBar.backgroundColor,
|
|
796
|
+
navigationBarTextColor: bars?.navigationBar.textColor,
|
|
797
|
+
tabBarHidden: bars?.tabBar.hidden ?? false
|
|
798
|
+
}, stack.pages);
|
|
799
|
+
};
|
|
360
800
|
const syncStack = () => {
|
|
361
801
|
const message = {
|
|
362
802
|
type: "syncStack",
|
|
@@ -366,6 +806,9 @@
|
|
|
366
806
|
}
|
|
367
807
|
};
|
|
368
808
|
broadcast(message);
|
|
809
|
+
const open = new Set(stack.pages.map((entry) => entry.instanceId));
|
|
810
|
+
for (const instanceId of barsByInstance.keys()) if (!open.has(instanceId)) barsByInstance.delete(instanceId);
|
|
811
|
+
showBars();
|
|
369
812
|
};
|
|
370
813
|
const syncSystemContext = () => {
|
|
371
814
|
broadcast({
|
|
@@ -381,13 +824,40 @@
|
|
|
381
824
|
if (stack.top !== previousTop) calls.dismissUI();
|
|
382
825
|
return true;
|
|
383
826
|
};
|
|
827
|
+
const openFirstPages = () => {
|
|
828
|
+
const [first, ...rest] = restorePages.filter((entry) => manifest.pages.includes(entry.page));
|
|
829
|
+
if (!first) {
|
|
830
|
+
navigate({
|
|
831
|
+
action: "reset",
|
|
832
|
+
page: manifest.entry,
|
|
833
|
+
options: {}
|
|
834
|
+
});
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
stack.apply({
|
|
838
|
+
action: "reset",
|
|
839
|
+
page: first.page,
|
|
840
|
+
options: first.options
|
|
841
|
+
});
|
|
842
|
+
for (const entry of rest) stack.apply({
|
|
843
|
+
action: "push",
|
|
844
|
+
page: entry.page,
|
|
845
|
+
options: entry.options
|
|
846
|
+
});
|
|
847
|
+
syncStack();
|
|
848
|
+
};
|
|
384
849
|
const navigateFromPage = ({ from, ...navigation }) => {
|
|
385
850
|
if (from === stack.top?.instanceId) navigate(navigation);
|
|
386
851
|
};
|
|
387
852
|
const hostMessageHandlers = /* @__PURE__ */ new Map([
|
|
388
853
|
["navigate", (payload) => navigateFromPage(payload)],
|
|
389
854
|
["hostCall", (payload) => calls.run(payload)],
|
|
390
|
-
["hostCancel", (payload) => calls.cancel(payload.id)]
|
|
855
|
+
["hostCancel", (payload) => calls.cancel(payload.id)],
|
|
856
|
+
["pageBars", (payload) => {
|
|
857
|
+
const { instanceId, ...bars } = payload;
|
|
858
|
+
barsByInstance.set(instanceId, bars);
|
|
859
|
+
showBars();
|
|
860
|
+
}]
|
|
391
861
|
]);
|
|
392
862
|
const stopService = logic.listen((raw) => {
|
|
393
863
|
const message = raw;
|
|
@@ -406,14 +876,13 @@
|
|
|
406
876
|
logic.post(message);
|
|
407
877
|
if (message.type === "connect") {
|
|
408
878
|
syncSystemContext();
|
|
409
|
-
|
|
410
|
-
action: "reset",
|
|
411
|
-
page: manifest.entry,
|
|
412
|
-
options: {}
|
|
413
|
-
});
|
|
879
|
+
openFirstPages();
|
|
414
880
|
}
|
|
415
881
|
});
|
|
416
882
|
return {
|
|
883
|
+
get pages() {
|
|
884
|
+
return stack.pages;
|
|
885
|
+
},
|
|
417
886
|
back: () => navigate({
|
|
418
887
|
action: "back",
|
|
419
888
|
delta: 1
|
|
@@ -436,10 +905,24 @@
|
|
|
436
905
|
//#region src/paths.ts
|
|
437
906
|
const CLIENT_PATH = "/__dot/";
|
|
438
907
|
const EVENTS_PATH = `${CLIENT_PATH}events`;
|
|
908
|
+
const HTTP_PATH = `${CLIENT_PATH}network/http/`;
|
|
909
|
+
const FILE_PATH = `${CLIENT_PATH}file/`;
|
|
439
910
|
const DOT_PATH = "/dot/";
|
|
440
911
|
const WEBVIEW_URL = `${DOT_PATH}ui/index.html`;
|
|
441
912
|
const MANIFEST_URL = `${DOT_PATH}manifest.json`;
|
|
442
913
|
//#endregion
|
|
914
|
+
//#region src/client/dash/dev-server.ts
|
|
915
|
+
async function callDevServer(path, params, signal) {
|
|
916
|
+
const answer = await (await fetch(path, {
|
|
917
|
+
method: "POST",
|
|
918
|
+
headers: { "Content-Type": "application/json" },
|
|
919
|
+
body: JSON.stringify(params),
|
|
920
|
+
signal
|
|
921
|
+
})).json();
|
|
922
|
+
if ("error" in answer) throw new HostError(answer.error.code, answer.error.message);
|
|
923
|
+
return answer.result;
|
|
924
|
+
}
|
|
925
|
+
//#endregion
|
|
443
926
|
//#region src/client/dash/system.ts
|
|
444
927
|
const SHAKE_DURATION_MS = 300;
|
|
445
928
|
const SHAKE = [
|
|
@@ -458,6 +941,30 @@
|
|
|
458
941
|
phone.dataset.torch = state;
|
|
459
942
|
note(`torch: ${state}`);
|
|
460
943
|
}
|
|
944
|
+
async function copyText(note, text) {
|
|
945
|
+
try {
|
|
946
|
+
await navigator.clipboard.writeText(text);
|
|
947
|
+
} catch (error) {
|
|
948
|
+
throw new HostError("failed", `The browser kept the clipboard: ${error.message}`);
|
|
949
|
+
}
|
|
950
|
+
note(`copied: ${text}`);
|
|
951
|
+
}
|
|
952
|
+
function share(note, params) {
|
|
953
|
+
const parts = [
|
|
954
|
+
params.text,
|
|
955
|
+
params.url,
|
|
956
|
+
params.file && `file ${params.file}`
|
|
957
|
+
].filter(Boolean);
|
|
958
|
+
if (parts.length === 0) throw new HostError("invalid", "Give share a text, a url or a file");
|
|
959
|
+
note(`shared: ${parts.join(" · ")}`);
|
|
960
|
+
}
|
|
961
|
+
function delay(milliseconds, signal) {
|
|
962
|
+
if (!Number.isFinite(milliseconds) || milliseconds < 0) throw new HostError("invalid", `A delay is a number of milliseconds, 0 or more, not ${milliseconds}`);
|
|
963
|
+
return new Promise((resolve) => {
|
|
964
|
+
const timer = setTimeout(resolve, milliseconds);
|
|
965
|
+
signal.addEventListener("abort", () => clearTimeout(timer));
|
|
966
|
+
});
|
|
967
|
+
}
|
|
461
968
|
//#endregion
|
|
462
969
|
//#region src/client/dom.ts
|
|
463
970
|
function element(selector) {
|
|
@@ -506,13 +1013,39 @@
|
|
|
506
1013
|
}
|
|
507
1014
|
//#endregion
|
|
508
1015
|
//#region src/client/dash/index.ts
|
|
1016
|
+
const HTTP_METHODS = [
|
|
1017
|
+
"request",
|
|
1018
|
+
"download",
|
|
1019
|
+
"upload"
|
|
1020
|
+
];
|
|
1021
|
+
const FILE_OPERATIONS = [
|
|
1022
|
+
"read",
|
|
1023
|
+
"write",
|
|
1024
|
+
"stat",
|
|
1025
|
+
"list",
|
|
1026
|
+
"createFolder",
|
|
1027
|
+
"move",
|
|
1028
|
+
"copy",
|
|
1029
|
+
"remove",
|
|
1030
|
+
"save",
|
|
1031
|
+
"open",
|
|
1032
|
+
"usage"
|
|
1033
|
+
];
|
|
509
1034
|
function dashHandlers(phone, note) {
|
|
510
1035
|
return {
|
|
511
1036
|
"dash.ui.alert": ({ params, signal }) => alert(phone, params, signal),
|
|
512
1037
|
"dash.system.vibrate": ({ params }) => vibrate(phone, note, params),
|
|
513
|
-
"dash.system.torch": ({ params }) => torch(phone, note, params.state)
|
|
1038
|
+
"dash.system.torch": ({ params }) => torch(phone, note, params.state),
|
|
1039
|
+
"dash.system.copyText": ({ params }) => copyText(note, params.text),
|
|
1040
|
+
"dash.system.share": ({ params }) => share(note, params),
|
|
1041
|
+
"dash.system.delay": ({ params, signal }) => delay(params.milliseconds, signal),
|
|
1042
|
+
...devServerHandlers("dash.network.http", HTTP_PATH, HTTP_METHODS),
|
|
1043
|
+
...devServerHandlers("dash.file", FILE_PATH, FILE_OPERATIONS)
|
|
514
1044
|
};
|
|
515
1045
|
}
|
|
1046
|
+
function devServerHandlers(group, path, names) {
|
|
1047
|
+
return Object.fromEntries(names.map((name) => [`${group}.${name}`, ({ params, signal }) => callDevServer(`${path}${name}`, params, signal)]));
|
|
1048
|
+
}
|
|
516
1049
|
//#endregion
|
|
517
1050
|
//#region src/client/dash/permissions.ts
|
|
518
1051
|
const PERMISSION_SUMMARIES = { account: "see your Dash account: your name, and your email or phone" };
|
|
@@ -567,10 +1100,15 @@
|
|
|
567
1100
|
const errorBanner = element("#error");
|
|
568
1101
|
const phone = element(".phone");
|
|
569
1102
|
const schemeSelect = element("#scheme");
|
|
1103
|
+
const navigationBar = element(".navigation-bar");
|
|
1104
|
+
const navigationTitle = element("#navigation-title");
|
|
1105
|
+
const navigationBack = element("#navigation-back");
|
|
1106
|
+
const tabBar = element(".tab-bar");
|
|
570
1107
|
const browserDark = matchMedia("(prefers-color-scheme: dark)");
|
|
571
1108
|
let runningApp = null;
|
|
572
1109
|
let launchCount = 0;
|
|
573
|
-
|
|
1110
|
+
let hotReloads = 0;
|
|
1111
|
+
async function launch(restorePages = []) {
|
|
574
1112
|
stopRunningApp();
|
|
575
1113
|
launchCount += 1;
|
|
576
1114
|
const thisLaunch = launchCount;
|
|
@@ -599,7 +1137,9 @@
|
|
|
599
1137
|
systemContext: systemContext(),
|
|
600
1138
|
handlers: dashHandlers(phone, note),
|
|
601
1139
|
askPermission: (request, signal) => askPermission(phone, note, request, signal),
|
|
602
|
-
observe: record
|
|
1140
|
+
observe: record,
|
|
1141
|
+
restorePages,
|
|
1142
|
+
onBarsChange: showBars
|
|
603
1143
|
});
|
|
604
1144
|
worker.addEventListener("error", (event) => showError(`Service crashed: ${event.message}`));
|
|
605
1145
|
screen.src = WEBVIEW_URL;
|
|
@@ -614,6 +1154,18 @@
|
|
|
614
1154
|
runningApp.worker.terminate();
|
|
615
1155
|
runningApp = null;
|
|
616
1156
|
}
|
|
1157
|
+
function showBars(bars, pages) {
|
|
1158
|
+
navigationBar.hidden = bars.navigationBarHidden;
|
|
1159
|
+
navigationTitle.textContent = bars.title;
|
|
1160
|
+
navigationBack.hidden = pages.length < 2;
|
|
1161
|
+
setBarColor("--bar", bars.navigationBarColor);
|
|
1162
|
+
setBarColor("--bar-text", bars.navigationBarTextColor);
|
|
1163
|
+
tabBar.hidden = bars.tabBarHidden;
|
|
1164
|
+
}
|
|
1165
|
+
function setBarColor(property, color) {
|
|
1166
|
+
if (color) phone.style.setProperty(property, color);
|
|
1167
|
+
else phone.style.removeProperty(property);
|
|
1168
|
+
}
|
|
617
1169
|
function goBack() {
|
|
618
1170
|
if (runningApp && !runningApp.host.back()) note("back on the first page: a device would close the dot");
|
|
619
1171
|
}
|
|
@@ -641,11 +1193,25 @@
|
|
|
641
1193
|
while (log.childElementCount > MAX_LOG_ENTRIES) log.firstElementChild?.remove();
|
|
642
1194
|
log.scrollTop = log.scrollHeight;
|
|
643
1195
|
}
|
|
644
|
-
function syncLaunch() {
|
|
645
|
-
launch().catch((error) => {
|
|
1196
|
+
function syncLaunch(restorePages = []) {
|
|
1197
|
+
launch(restorePages).catch((error) => {
|
|
646
1198
|
showError(`Could not start the dot: ${String(error)}`);
|
|
647
1199
|
});
|
|
648
1200
|
}
|
|
1201
|
+
function relaunch() {
|
|
1202
|
+
syncLaunch(runningApp?.host.pages ?? []);
|
|
1203
|
+
}
|
|
1204
|
+
function hotReload() {
|
|
1205
|
+
if (!runningApp) {
|
|
1206
|
+
syncLaunch();
|
|
1207
|
+
return;
|
|
1208
|
+
}
|
|
1209
|
+
hotReloads += 1;
|
|
1210
|
+
const reload = { dotHotReload: hotReloads };
|
|
1211
|
+
runningApp.worker.postMessage(reload);
|
|
1212
|
+
screen.contentWindow?.postMessage(reload, location.origin);
|
|
1213
|
+
note("dot updated in place");
|
|
1214
|
+
}
|
|
649
1215
|
function showError(message) {
|
|
650
1216
|
errorBanner.hidden = message === null;
|
|
651
1217
|
errorBanner.textContent = message ?? "";
|
|
@@ -671,11 +1237,16 @@
|
|
|
671
1237
|
const events = new EventSource(EVENTS_PATH);
|
|
672
1238
|
events.addEventListener("reload", () => {
|
|
673
1239
|
showError(null);
|
|
674
|
-
|
|
1240
|
+
relaunch();
|
|
1241
|
+
});
|
|
1242
|
+
events.addEventListener("hot-reload", () => {
|
|
1243
|
+
showError(null);
|
|
1244
|
+
hotReload();
|
|
675
1245
|
});
|
|
676
1246
|
events.addEventListener("build-error", (event) => showError(String(event.data)));
|
|
677
|
-
element("#reload").addEventListener("click", syncLaunch);
|
|
1247
|
+
element("#reload").addEventListener("click", () => syncLaunch());
|
|
678
1248
|
element("#back").addEventListener("click", goBack);
|
|
1249
|
+
navigationBack.addEventListener("click", goBack);
|
|
679
1250
|
element("#clear").addEventListener("click", () => log.replaceChildren());
|
|
680
1251
|
schemeSelect.addEventListener("change", () => changeScheme(schemeSelect.value));
|
|
681
1252
|
browserDark.addEventListener("change", () => changeScheme(browserScheme()));
|