@monimesl/dot-simulator 0.1.0-alpha.7 → 0.1.0-alpha.9

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.
@@ -20,7 +20,8 @@
20
20
  props: {
21
21
  value: "number",
22
22
  currency: "string",
23
- decimals: "number",
23
+ minorUnits: "number",
24
+ unit: ["minor", "major"],
24
25
  label: "string",
25
26
  placeholder: "string",
26
27
  hint: "string",
@@ -51,6 +52,22 @@
51
52
  "medium",
52
53
  "large"
53
54
  ];
55
+ const PADDING_PROPS = {
56
+ padding: SPACES,
57
+ paddingTop: SPACES,
58
+ paddingStart: SPACES,
59
+ paddingEnd: SPACES,
60
+ paddingBottom: SPACES
61
+ };
62
+ const ASPECTS = [
63
+ "1:1",
64
+ "4:3",
65
+ "3:2",
66
+ "16:9",
67
+ "3:4",
68
+ "2:3",
69
+ "9:16"
70
+ ];
54
71
  const TONES = [
55
72
  "default",
56
73
  "muted",
@@ -89,26 +106,33 @@
89
106
  "download",
90
107
  "edit",
91
108
  "error",
109
+ "external-link",
92
110
  "eye",
93
111
  "eye-off",
94
112
  "file",
95
113
  "gift",
114
+ "globe",
96
115
  "grid",
116
+ "headphones",
97
117
  "heart",
98
118
  "help",
99
119
  "history",
100
120
  "home",
101
121
  "image",
102
122
  "info",
123
+ "link",
103
124
  "list",
104
125
  "location",
105
126
  "lock",
106
127
  "logout",
107
128
  "mail",
129
+ "microphone",
108
130
  "minus",
109
131
  "mobile",
110
132
  "more",
133
+ "music",
111
134
  "phone",
135
+ "playlist",
112
136
  "plus",
113
137
  "qr-code",
114
138
  "receipt",
@@ -119,10 +143,12 @@
119
143
  "share",
120
144
  "star",
121
145
  "success",
146
+ "ticket",
122
147
  "trash",
123
148
  "upload",
124
149
  "user",
125
150
  "users",
151
+ "video",
126
152
  "wallet",
127
153
  "warning",
128
154
  "water",
@@ -137,7 +163,8 @@
137
163
  indicator: ["dots", "none"],
138
164
  gap: SPACES,
139
165
  effect: ["slide", "scale"],
140
- index: "number"
166
+ index: "number",
167
+ ...PADDING_PROPS
141
168
  },
142
169
  events: ["change"],
143
170
  children: "elements"
@@ -167,6 +194,21 @@
167
194
  events: ["change", "complete"],
168
195
  children: "none"
169
196
  });
197
+ const DetailRow = defineComponent({
198
+ name: "DetailRow",
199
+ props: {
200
+ label: "string",
201
+ value: "string",
202
+ tone: TONES,
203
+ weight: [
204
+ "regular",
205
+ "medium",
206
+ "bold"
207
+ ],
208
+ ...PADDING_PROPS
209
+ },
210
+ children: "none"
211
+ });
170
212
  const Divider = defineComponent({
171
213
  name: "Divider",
172
214
  children: "none"
@@ -176,7 +218,8 @@
176
218
  props: {
177
219
  icon: ICON_NAMES,
178
220
  title: "string",
179
- text: "string"
221
+ text: "string",
222
+ ...PADDING_PROPS
180
223
  },
181
224
  children: "elements"
182
225
  });
@@ -194,7 +237,8 @@
194
237
  name: "Notice",
195
238
  props: {
196
239
  tone: STATUS_TONES,
197
- title: "string"
240
+ title: "string",
241
+ ...PADDING_PROPS
198
242
  },
199
243
  children: "text"
200
244
  });
@@ -205,13 +249,15 @@
205
249
  });
206
250
  const Footer = defineComponent({
207
251
  name: "Footer",
252
+ props: PADDING_PROPS,
208
253
  children: "elements"
209
254
  });
210
255
  const Grid = defineComponent({
211
256
  name: "Grid",
212
257
  props: {
213
258
  columns: "number",
214
- gap: SPACES
259
+ gap: SPACES,
260
+ ...PADDING_PROPS
215
261
  },
216
262
  children: "elements"
217
263
  });
@@ -248,10 +294,16 @@
248
294
  "rounded",
249
295
  "square",
250
296
  "circle"
251
- ]
297
+ ],
298
+ aspect: ASPECTS
252
299
  },
253
300
  events: ["load", "error"],
254
- children: "none"
301
+ children: "none",
302
+ overrides: [{
303
+ prop: "aspect",
304
+ ignores: "height",
305
+ because: "the aspect sets the height"
306
+ }]
255
307
  });
256
308
  const Input = defineComponent({
257
309
  name: "Input",
@@ -276,9 +328,23 @@
276
328
  events: ["change", "submit"],
277
329
  children: "none"
278
330
  });
331
+ const Link = defineComponent({
332
+ name: "Link",
333
+ props: {
334
+ href: "string",
335
+ tone: TONES
336
+ },
337
+ events: ["tap"],
338
+ children: "text",
339
+ inline: true
340
+ });
279
341
  const List = defineComponent({
280
342
  name: "List",
281
- props: { size: ["sm", "md"] },
343
+ props: {
344
+ size: ["sm", "md"],
345
+ ...PADDING_PROPS
346
+ },
347
+ events: ["endReached"],
282
348
  children: "elements"
283
349
  });
284
350
  const ListItem = defineComponent({
@@ -288,7 +354,8 @@
288
354
  subtitle: "string",
289
355
  value: "string",
290
356
  icon: ICON_NAMES,
291
- image: "string"
357
+ image: "string",
358
+ ...PADDING_PROPS
292
359
  },
293
360
  events: ["tap"],
294
361
  children: "elements"
@@ -298,7 +365,8 @@
298
365
  props: {
299
366
  open: "boolean",
300
367
  title: "string",
301
- showCloseIcon: "boolean"
368
+ showCloseIcon: "boolean",
369
+ ...PADDING_PROPS
302
370
  },
303
371
  events: ["close"],
304
372
  children: "elements"
@@ -343,6 +411,21 @@
343
411
  },
344
412
  children: "none"
345
413
  });
414
+ const Scroll = defineComponent({
415
+ name: "Scroll",
416
+ props: {
417
+ gap: SPACES,
418
+ snap: [
419
+ "none",
420
+ "start",
421
+ "center"
422
+ ],
423
+ index: "number",
424
+ ...PADDING_PROPS
425
+ },
426
+ events: ["change"],
427
+ children: "elements"
428
+ });
346
429
  const Skeleton = defineComponent({
347
430
  name: "Skeleton",
348
431
  props: {
@@ -360,7 +443,8 @@
360
443
  name: "Tabs",
361
444
  props: {
362
445
  value: "string",
363
- variant: ["underline", "segmented"]
446
+ variant: ["underline", "segmented"],
447
+ ...PADDING_PROPS
364
448
  },
365
449
  events: ["change"],
366
450
  children: "elements"
@@ -393,7 +477,8 @@
393
477
  "center",
394
478
  "end"
395
479
  ],
396
- maxLines: "number"
480
+ maxLines: "number",
481
+ ...PADDING_PROPS
397
482
  },
398
483
  children: "text",
399
484
  inline: true
@@ -451,6 +536,7 @@
451
536
  Checkbox,
452
537
  Chip,
453
538
  CodeInput,
539
+ DetailRow,
454
540
  Divider,
455
541
  EmptyState,
456
542
  Footer,
@@ -459,6 +545,7 @@
459
545
  Icon,
460
546
  Image,
461
547
  Input,
548
+ Link,
462
549
  List,
463
550
  ListItem,
464
551
  Notice,
@@ -475,6 +562,7 @@
475
562
  children: "none"
476
563
  }),
477
564
  RadioGroup,
565
+ Scroll,
478
566
  Select,
479
567
  Sheet,
480
568
  Skeleton,
@@ -504,11 +592,7 @@
504
592
  ],
505
593
  wrap: "boolean",
506
594
  grow: "boolean",
507
- padding: SPACES,
508
- paddingTop: SPACES,
509
- paddingStart: SPACES,
510
- paddingEnd: SPACES,
511
- paddingBottom: SPACES,
595
+ ...PADDING_PROPS,
512
596
  variant: ["plain", "card"]
513
597
  },
514
598
  events: ["tap"],
@@ -600,10 +684,6 @@
600
684
  get top() {
601
685
  return this.#pages.at(-1);
602
686
  }
603
- /**
604
- * Applies a navigation, or refuses it and returns false: a push onto a full stack, or going back
605
- * from the first page (which the host handles itself, e.g. by closing the dot).
606
- */
607
687
  apply(navigation) {
608
688
  switch (navigation.action) {
609
689
  case "push":
@@ -642,10 +722,10 @@
642
722
  }
643
723
  };
644
724
  function checkCompatibility(manifest, { dashVersion, minRuntimeVersion, reactVersions }) {
645
- if (!isVersionAtLeast(manifest.runtime, minRuntimeVersion)) throw new IncompatibleDotError("runtimeTooOld", `This dot was built with Dot runtime ${manifest.runtime}, but this host runs ${minRuntimeVersion} or newer. Rebuild it with a newer @monimesl/dot-runtime.`);
725
+ if (!isVersionAtLeast(manifest.runtime, minRuntimeVersion)) throw new IncompatibleDotError("runtimeTooOld", `This dot was built with an old Dot runtime, ${manifest.runtime}. Rebuild it with @monimesl/dot-runtime ${minRuntimeVersion} or newer.`);
646
726
  const minDashVersion = manifest.dash?.minVersion;
647
- if (minDashVersion !== void 0 && !isVersionAtLeast(dashVersion, minDashVersion)) throw new IncompatibleDotError("dashTooOld", `This dot needs Dash ${minDashVersion} or newer, and this is Dash ${dashVersion}.`);
648
- if (reactVersions !== void 0 && !reactVersions.some((version) => isReactCompatible(version, manifest.react))) throw new IncompatibleDotError("reactUnavailable", `This dot needs React ${manifest.react} or a newer ${majorVersion(manifest.react)}.x, which this host doesn't ship.`);
727
+ if (minDashVersion !== void 0 && !isVersionAtLeast(dashVersion, minDashVersion)) throw new IncompatibleDotError("dashTooOld", `This dot needs Dash ${minDashVersion} or newer. This is Dash ${dashVersion}.`);
728
+ if (reactVersions !== void 0 && !reactVersions.some((version) => isReactCompatible(version, manifest.react))) throw new IncompatibleDotError("reactUnavailable", `This dot needs React ${manifest.react}, which this host doesn't have.`);
649
729
  }
650
730
  //#endregion
651
731
  //#region src/host-calls.ts
@@ -667,7 +747,7 @@
667
747
  id,
668
748
  error: {
669
749
  code: "unsupported",
670
- message: `This host has no "${method}"`
750
+ message: `This host doesn't support "${method}"`
671
751
  }
672
752
  });
673
753
  return;
@@ -690,7 +770,7 @@
690
770
  this.#end(id)?.controller.abort();
691
771
  }
692
772
  dismissUI() {
693
- for (const [id, call] of this.#running) if (call.method.startsWith(UI_METHOD_PREFIX)) this.#fail(id, new HostError("cancelled", "The page it was shown on is no longer on top"));
773
+ for (const [id, call] of this.#running) if (call.method.startsWith(UI_METHOD_PREFIX)) this.#fail(id, new HostError("cancelled", "Its page is no longer on screen"));
694
774
  }
695
775
  async #invoke(id, entry, call) {
696
776
  try {
@@ -752,7 +832,7 @@
752
832
  }
753
833
  async check(method, permission, signal) {
754
834
  const reason = this.#declared[permission];
755
- if (reason === void 0) throw new HostError("denied", `"${method}" needs the "${permission}" permission. Add it to dot.json's permissions, with the reason Dash shows the person.`);
835
+ if (reason === void 0) throw new HostError("denied", `"${method}" needs the "${permission}" permission. Add it to permissions in dot.json, with a reason to show the person.`);
756
836
  let allowed = this.#answers.get(permission);
757
837
  if (allowed === void 0) {
758
838
  allowed = await this.#ask({
@@ -762,7 +842,7 @@
762
842
  }, signal);
763
843
  this.#answers.set(permission, allowed);
764
844
  }
765
- if (!allowed) throw new HostError("denied", `The person did not allow "${permission}"`);
845
+ if (!allowed) throw new HostError("denied", `The person didn't allow "${permission}"`);
766
846
  }
767
847
  };
768
848
  //#endregion
@@ -908,7 +988,9 @@
908
988
  const CLIENT_PATH = "/__dot/";
909
989
  const EVENTS_PATH = `${CLIENT_PATH}events`;
910
990
  const HTTP_PATH = `${CLIENT_PATH}network/http/`;
911
- const FILE_PATH = `${CLIENT_PATH}file/`;
991
+ const FILE_PATH = `${CLIENT_PATH}storage/file/`;
992
+ const CACHE_PATH = `${CLIENT_PATH}storage/cache/`;
993
+ const SECRET_PATH = `${CLIENT_PATH}storage/secret/`;
912
994
  const DOT_PATH = "/dot/";
913
995
  const WEBVIEW_URL = `${DOT_PATH}ui/index.html`;
914
996
  const MANIFEST_URL = `${DOT_PATH}manifest.json`;
@@ -947,7 +1029,7 @@
947
1029
  try {
948
1030
  await navigator.clipboard.writeText(text);
949
1031
  } catch (error) {
950
- throw new HostError("failed", `The browser kept the clipboard: ${error.message}`);
1032
+ throw new HostError("failed", `The browser blocked the clipboard: ${error.message}`);
951
1033
  }
952
1034
  note(`copied: ${text}`);
953
1035
  }
@@ -957,9 +1039,21 @@
957
1039
  params.url,
958
1040
  params.file && `file ${params.file}`
959
1041
  ].filter(Boolean);
960
- if (parts.length === 0) throw new HostError("invalid", "Give share a text, a url or a file");
1042
+ if (parts.length === 0) throw new HostError("invalid", "share needs a text, a url or a file");
961
1043
  note(`shared: ${parts.join(" · ")}`);
962
1044
  }
1045
+ function openUrl(note, url) {
1046
+ if (!isHttps(url)) throw new HostError("invalid", `Dash only opens https addresses, not ${url}`);
1047
+ window.open(url, "_blank", "noopener");
1048
+ note(`opened: ${url}`);
1049
+ }
1050
+ function isHttps(url) {
1051
+ try {
1052
+ return new URL(url).protocol === "https:";
1053
+ } catch {
1054
+ return false;
1055
+ }
1056
+ }
963
1057
  function delay(milliseconds, signal) {
964
1058
  if (!Number.isFinite(milliseconds) || milliseconds < 0) throw new HostError("invalid", `A delay is a number of milliseconds, 0 or more, not ${milliseconds}`);
965
1059
  return new Promise((resolve) => {
@@ -1033,6 +1127,20 @@
1033
1127
  "open",
1034
1128
  "usage"
1035
1129
  ];
1130
+ const CACHE_OPERATIONS = [
1131
+ "get",
1132
+ "set",
1133
+ "remove",
1134
+ "exists",
1135
+ "keys",
1136
+ "clear"
1137
+ ];
1138
+ const SECRET_OPERATIONS = [
1139
+ "get",
1140
+ "set",
1141
+ "remove",
1142
+ "clear"
1143
+ ];
1036
1144
  function dashHandlers(phone, note) {
1037
1145
  return {
1038
1146
  "dash.ui.alert": ({ params, signal }) => alert(phone, params, signal),
@@ -1040,9 +1148,12 @@
1040
1148
  "dash.system.torch": ({ params }) => torch(phone, note, params.state),
1041
1149
  "dash.system.copyText": ({ params }) => copyText(note, params.text),
1042
1150
  "dash.system.share": ({ params }) => share(note, params),
1151
+ "dash.system.openUrl": ({ params }) => openUrl(note, params.url),
1043
1152
  "dash.system.delay": ({ params, signal }) => delay(params.milliseconds, signal),
1044
1153
  ...devServerHandlers("dash.network.http", HTTP_PATH, HTTP_METHODS),
1045
- ...devServerHandlers("dash.file", FILE_PATH, FILE_OPERATIONS)
1154
+ ...devServerHandlers("dash.storage.file", FILE_PATH, FILE_OPERATIONS),
1155
+ ...devServerHandlers("dash.storage.cache", CACHE_PATH, CACHE_OPERATIONS),
1156
+ ...devServerHandlers("dash.storage.secret", SECRET_PATH, SECRET_OPERATIONS)
1046
1157
  };
1047
1158
  }
1048
1159
  function devServerHandlers(group, path, names) {
@@ -1101,21 +1212,17 @@
1101
1212
  const log = element("#log");
1102
1213
  const errorBanner = element("#error");
1103
1214
  const phone = element(".phone");
1104
- const platformSelect = element("#platform");
1105
- const inputModeSelect = element("#input-mode");
1106
1215
  const schemeSelect = element("#scheme");
1107
1216
  const navigationBar = element(".navigation-bar");
1108
1217
  const navigationTitle = element("#navigation-title");
1109
1218
  const navigationBack = element("#navigation-back");
1110
1219
  const tabBar = element(".tab-bar");
1111
1220
  const browserDark = matchMedia("(prefers-color-scheme: dark)");
1112
- const COARSE_POINTER_MEDIA = /\(\s*(?:any-)?pointer\s*:\s*coarse\s*\)/gi;
1113
- const EMULATED_TOUCH_STYLE = "data-dot-simulator-touch";
1114
- let runningApp = null;
1221
+ let runningDot = null;
1115
1222
  let launchCount = 0;
1116
1223
  let hotReloads = 0;
1117
1224
  async function launch(restorePages = []) {
1118
- stopRunningApp();
1225
+ stopRunningDot();
1119
1226
  launchCount += 1;
1120
1227
  const thisLaunch = launchCount;
1121
1228
  if (log.childElementCount > 0) note("dot restarted");
@@ -1149,16 +1256,16 @@
1149
1256
  });
1150
1257
  worker.addEventListener("error", (event) => showError(`Service crashed: ${event.message}`));
1151
1258
  screen.src = WEBVIEW_URL;
1152
- runningApp = {
1259
+ runningDot = {
1153
1260
  host,
1154
1261
  worker
1155
1262
  };
1156
1263
  }
1157
- function stopRunningApp() {
1158
- if (!runningApp) return;
1159
- runningApp.host.stop();
1160
- runningApp.worker.terminate();
1161
- runningApp = null;
1264
+ function stopRunningDot() {
1265
+ if (!runningDot) return;
1266
+ runningDot.host.stop();
1267
+ runningDot.worker.terminate();
1268
+ runningDot = null;
1162
1269
  }
1163
1270
  function showBars(bars, pages) {
1164
1271
  navigationBar.hidden = bars.navigationBarHidden;
@@ -1173,7 +1280,7 @@
1173
1280
  else phone.style.removeProperty(property);
1174
1281
  }
1175
1282
  function goBack() {
1176
- if (runningApp && !runningApp.host.back()) note("back on the first page: a device would close the dot");
1283
+ if (runningDot && !runningDot.host.back()) note("back on the first page: a device would close the dot");
1177
1284
  }
1178
1285
  const ARROWS = {
1179
1286
  toHost: "both --> host",
@@ -1199,22 +1306,22 @@
1199
1306
  while (log.childElementCount > MAX_LOG_ENTRIES) log.firstElementChild?.remove();
1200
1307
  log.scrollTop = log.scrollHeight;
1201
1308
  }
1202
- function syncLaunch(restorePages = []) {
1309
+ function restart(restorePages = []) {
1203
1310
  launch(restorePages).catch((error) => {
1204
1311
  showError(`Could not start the dot: ${String(error)}`);
1205
1312
  });
1206
1313
  }
1207
1314
  function relaunch() {
1208
- syncLaunch(runningApp?.host.pages ?? []);
1315
+ restart(runningDot?.host.pages ?? []);
1209
1316
  }
1210
1317
  function hotReload() {
1211
- if (!runningApp) {
1212
- syncLaunch();
1318
+ if (!runningDot) {
1319
+ restart();
1213
1320
  return;
1214
1321
  }
1215
1322
  hotReloads += 1;
1216
1323
  const reload = { dotHotReload: hotReloads };
1217
- runningApp.worker.postMessage(reload);
1324
+ runningDot.worker.postMessage(reload);
1218
1325
  screen.contentWindow?.postMessage(reload, location.origin);
1219
1326
  note("dot updated in place");
1220
1327
  }
@@ -1222,9 +1329,11 @@
1222
1329
  errorBanner.hidden = message === null;
1223
1330
  errorBanner.textContent = message ?? "";
1224
1331
  }
1332
+ function syncSystemContext() {
1333
+ runningDot?.host.setSystemContext(systemContext());
1334
+ }
1225
1335
  function systemContext() {
1226
1336
  return {
1227
- platform: platformSelect.value,
1228
1337
  scheme: schemeSelect.value,
1229
1338
  appState: appState()
1230
1339
  };
@@ -1239,55 +1348,7 @@
1239
1348
  function changeScheme(scheme) {
1240
1349
  schemeSelect.value = scheme;
1241
1350
  phone.dataset.scheme = scheme;
1242
- runningApp?.host.setSystemContext(systemContext());
1243
- }
1244
- function changeInputMode(mode) {
1245
- inputModeSelect.value = mode;
1246
- phone.dataset.inputMode = mode;
1247
- applyInputMode();
1248
- }
1249
- function applyInputMode() {
1250
- const document = screen.contentDocument;
1251
- if (!document) return;
1252
- document.documentElement.dataset.dotSimulatorInput = inputModeSelect.value;
1253
- document.querySelector(`style[${EMULATED_TOUCH_STYLE}]`)?.remove();
1254
- if (inputModeSelect.value !== "touch") return;
1255
- const css = coarsePointerCss(document);
1256
- if (!css) return;
1257
- const style = document.createElement("style");
1258
- style.setAttribute(EMULATED_TOUCH_STYLE, "");
1259
- style.textContent = css;
1260
- document.head.append(style);
1261
- }
1262
- function coarsePointerCss(document) {
1263
- let css = "";
1264
- for (const sheet of document.styleSheets) try {
1265
- css += coarsePointerRules(sheet.cssRules);
1266
- } catch {}
1267
- return css;
1268
- }
1269
- function coarsePointerRules(rules) {
1270
- let css = "";
1271
- for (const rule of rules) {
1272
- const nestedRules = rule.cssRules;
1273
- if (!nestedRules) continue;
1274
- if (rule.type === CSSRule.MEDIA_RULE) {
1275
- const media = rule;
1276
- COARSE_POINTER_MEDIA.lastIndex = 0;
1277
- if (COARSE_POINTER_MEDIA.test(media.conditionText)) {
1278
- COARSE_POINTER_MEDIA.lastIndex = 0;
1279
- const condition = media.conditionText.replace(COARSE_POINTER_MEDIA, "(min-width: 0px)");
1280
- const contents = Array.from(media.cssRules, (child) => child.cssText).join("\n");
1281
- css += condition === "(min-width: 0px)" ? contents : `@media ${condition}{${contents}}`;
1282
- continue;
1283
- }
1284
- }
1285
- const contents = coarsePointerRules(nestedRules);
1286
- if (!contents) continue;
1287
- const openingBrace = rule.cssText.indexOf("{");
1288
- if (openingBrace !== -1) css += `${rule.cssText.slice(0, openingBrace)}{${contents}}`;
1289
- }
1290
- return css;
1351
+ syncSystemContext();
1291
1352
  }
1292
1353
  const events = new EventSource(EVENTS_PATH);
1293
1354
  events.addEventListener("reload", () => {
@@ -1299,24 +1360,15 @@
1299
1360
  hotReload();
1300
1361
  });
1301
1362
  events.addEventListener("build-error", (event) => showError(String(event.data)));
1302
- element("#reload").addEventListener("click", () => syncLaunch());
1363
+ element("#reload").addEventListener("click", () => restart());
1303
1364
  element("#back").addEventListener("click", goBack);
1304
1365
  navigationBack.addEventListener("click", goBack);
1305
1366
  element("#clear").addEventListener("click", () => log.replaceChildren());
1306
1367
  schemeSelect.addEventListener("change", () => changeScheme(schemeSelect.value));
1307
- inputModeSelect.addEventListener("change", () => changeInputMode(inputModeSelect.value));
1308
- platformSelect.addEventListener("change", () => {
1309
- phone.dataset.platform = platformSelect.value;
1310
- runningApp?.host.setSystemContext(systemContext());
1311
- });
1312
- screen.addEventListener("load", applyInputMode);
1313
1368
  browserDark.addEventListener("change", () => changeScheme(browserScheme()));
1314
- document.addEventListener("visibilitychange", () => {
1315
- runningApp?.host.setSystemContext(systemContext());
1316
- });
1369
+ document.addEventListener("visibilitychange", syncSystemContext);
1317
1370
  changeScheme(browserScheme());
1318
- changeInputMode("touch");
1319
- syncLaunch();
1371
+ restart();
1320
1372
  //#endregion
1321
1373
  })();
1322
1374