dsh-mobile 0.8.5 → 0.8.6
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/CHANGELOG.md +19 -1
- package/CONTRIBUTORS.md +10 -4
- package/README.en.md +3 -2
- package/README.md +3 -2
- package/apps/mobile/README.md +2 -0
- package/apps/mobile/README.zh-CN.md +2 -0
- package/docs/CLIENT_MODULES.en.md +1 -1
- package/docs/CLIENT_MODULES.md +1 -1
- package/docs/README.md +1 -1
- package/docs/WEB_PUSH.en.md +20 -4
- package/docs/WEB_PUSH.md +20 -4
- package/lib/cli.js +104 -9
- package/lib/cli.js.map +1 -1
- package/lib/client.js +207 -14
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +40 -1
- package/lib/index.mjs +373 -31
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/packages/question-fixes/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -3791,6 +3791,28 @@ window.__ModuleLoader__.load({
|
|
|
3791
3791
|
if (bridge === void 0 || typeof bridge.capabilities !== "function" || typeof bridge.invoke !== "function") return void 0;
|
|
3792
3792
|
return bridge;
|
|
3793
3793
|
}
|
|
3794
|
+
/** Encode one opaque Session id for the App's internal notification route. */
|
|
3795
|
+
function taskNotificationNavigate(sessionId) {
|
|
3796
|
+
if (sessionId === "") return void 0;
|
|
3797
|
+
const bytes = new TextEncoder().encode(sessionId);
|
|
3798
|
+
let binary = "";
|
|
3799
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
3800
|
+
const route = `/?dsh-session=${globalThis.btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/u, "")}`;
|
|
3801
|
+
return route.length <= 270 ? route : void 0;
|
|
3802
|
+
}
|
|
3803
|
+
/** Decode only the App's bounded internal Session route. */
|
|
3804
|
+
function decodeTaskNotificationNavigate(value) {
|
|
3805
|
+
if (value === null || value === void 0 || !/^[A-Za-z0-9_-]{1,256}$/u.test(value)) return void 0;
|
|
3806
|
+
try {
|
|
3807
|
+
const padded = value.replaceAll("-", "+").replaceAll("_", "/") + "=".repeat((4 - value.length % 4) % 4);
|
|
3808
|
+
const binary = globalThis.atob(padded);
|
|
3809
|
+
const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
3810
|
+
const decoded = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
3811
|
+
return decoded === "" ? void 0 : decoded;
|
|
3812
|
+
} catch {
|
|
3813
|
+
return;
|
|
3814
|
+
}
|
|
3815
|
+
}
|
|
3794
3816
|
/** Parse a `task-notify` SSE payload; rejects anything malformed or empty. */
|
|
3795
3817
|
function parseTaskNotifyPayload(value) {
|
|
3796
3818
|
let record;
|
|
@@ -3845,7 +3867,8 @@ window.__ModuleLoader__.load({
|
|
|
3845
3867
|
return bridge.invoke("notification.notify", {
|
|
3846
3868
|
title: event.title,
|
|
3847
3869
|
body: event.body,
|
|
3848
|
-
tag: event.tag
|
|
3870
|
+
tag: event.tag,
|
|
3871
|
+
...event.navigate === void 0 ? {} : { navigate: event.navigate }
|
|
3849
3872
|
});
|
|
3850
3873
|
}).then(() => void 0, (error) => {
|
|
3851
3874
|
const code = typeof error === "object" && error !== null && "code" in error ? String(error.code) : "";
|
|
@@ -9582,10 +9605,7 @@ window.__ModuleLoader__.load({
|
|
|
9582
9605
|
});
|
|
9583
9606
|
if (currentHostSubscription) consentedSubscriptions.delete(currentHostSubscription);
|
|
9584
9607
|
currentHostSubscription = void 0;
|
|
9585
|
-
|
|
9586
|
-
if (sub) {
|
|
9587
|
-
if (await sub.unsubscribe().catch(() => false) && ownedSubscription === sub) ownedSubscription = void 0;
|
|
9588
|
-
}
|
|
9608
|
+
ownedSubscription = void 0;
|
|
9589
9609
|
if (await refresh(token) && current(token) && operation === attempt && config?.status === "disabled") publish({
|
|
9590
9610
|
state: "disabled",
|
|
9591
9611
|
preferences: config.preferences
|
|
@@ -9746,7 +9766,13 @@ window.__ModuleLoader__.load({
|
|
|
9746
9766
|
const MOBILE_PUSH_SETTINGS_COPY = {
|
|
9747
9767
|
en: {
|
|
9748
9768
|
title: "Web push notifications",
|
|
9749
|
-
desc: "Receive notifications when this page is closed.",
|
|
9769
|
+
desc: "Receive notifications when this page is closed. Disable stops sends but keeps the browser subscription so it can be reused safely.",
|
|
9770
|
+
permission: {
|
|
9771
|
+
granted: "System permission: granted. A reinstalled Home Screen app can inherit this site-level grant.",
|
|
9772
|
+
default: "System permission: not decided.",
|
|
9773
|
+
denied: "System permission: blocked.",
|
|
9774
|
+
unknown: "System permission: unavailable."
|
|
9775
|
+
},
|
|
9750
9776
|
enable: "Enable",
|
|
9751
9777
|
disable: "Disable",
|
|
9752
9778
|
test: "Send test",
|
|
@@ -9771,7 +9797,13 @@ window.__ModuleLoader__.load({
|
|
|
9771
9797
|
},
|
|
9772
9798
|
zh: {
|
|
9773
9799
|
title: "网页推送通知",
|
|
9774
|
-
desc: "
|
|
9800
|
+
desc: "关闭此页面后仍可接收通知。停用会停止发送,但保留浏览器订阅,便于安全地重新启用。",
|
|
9801
|
+
permission: {
|
|
9802
|
+
granted: "系统权限:已允许。重新安装的主屏幕 App 可能继承站点级授权。",
|
|
9803
|
+
default: "系统权限:尚未选择。",
|
|
9804
|
+
denied: "系统权限:已阻止。",
|
|
9805
|
+
unknown: "系统权限:不可读取。"
|
|
9806
|
+
},
|
|
9775
9807
|
enable: "启用",
|
|
9776
9808
|
disable: "停用",
|
|
9777
9809
|
test: "发送测试",
|
|
@@ -9796,7 +9828,13 @@ window.__ModuleLoader__.load({
|
|
|
9796
9828
|
},
|
|
9797
9829
|
it: {
|
|
9798
9830
|
title: "Notifiche Web push",
|
|
9799
|
-
desc: "Ricevi notifiche quando la pagina è chiusa.",
|
|
9831
|
+
desc: "Ricevi notifiche quando la pagina è chiusa. La disattivazione interrompe gli invii ma conserva l’iscrizione del browser per poterla riutilizzare.",
|
|
9832
|
+
permission: {
|
|
9833
|
+
granted: "Permesso di sistema: concesso. Una Web App reinstallata può ereditare questa autorizzazione del sito.",
|
|
9834
|
+
default: "Permesso di sistema: non ancora scelto.",
|
|
9835
|
+
denied: "Permesso di sistema: bloccato.",
|
|
9836
|
+
unknown: "Permesso di sistema: non disponibile."
|
|
9837
|
+
},
|
|
9800
9838
|
enable: "Attiva",
|
|
9801
9839
|
disable: "Disattiva",
|
|
9802
9840
|
test: "Invia test",
|
|
@@ -9845,6 +9883,7 @@ window.__ModuleLoader__.load({
|
|
|
9845
9883
|
if (snapshot.state === "unsupported") return null;
|
|
9846
9884
|
const prefs = snapshot.preferences;
|
|
9847
9885
|
const Switch = switchComponent ?? requirePublicMobilePushSwitch();
|
|
9886
|
+
const permission = typeof Notification === "undefined" ? "unknown" : Notification.permission;
|
|
9848
9887
|
const toggle = (key, checked) => {
|
|
9849
9888
|
if (!prefs) return;
|
|
9850
9889
|
controller.updatePreferences({
|
|
@@ -9866,7 +9905,7 @@ window.__ModuleLoader__.load({
|
|
|
9866
9905
|
}, (0, react.createElement)("div", { className: "dsh-mobile-settings_title" }, copy.title), (0, react.createElement)("div", {
|
|
9867
9906
|
className: "dsh-mobile-settings_desc",
|
|
9868
9907
|
"aria-live": "polite"
|
|
9869
|
-
}, message(snapshot, copy)), prefs && Switch !== void 0 ? (0, react.createElement)("div", { className: "dsh-mobile-push-categories" }, ...KEYS.map((key, index) => {
|
|
9908
|
+
}, message(snapshot, copy)), (0, react.createElement)("div", { className: "dsh-mobile-settings_desc" }, copy.permission[permission]), prefs && Switch !== void 0 ? (0, react.createElement)("div", { className: "dsh-mobile-push-categories" }, ...KEYS.map((key, index) => {
|
|
9870
9909
|
const name = copy.categories[index];
|
|
9871
9910
|
if (name === void 0) return null;
|
|
9872
9911
|
return (0, react.createElement)("label", {
|
|
@@ -9907,7 +9946,6 @@ window.__ModuleLoader__.load({
|
|
|
9907
9946
|
}, copy.busy)));
|
|
9908
9947
|
}
|
|
9909
9948
|
// src/mobile-push/navigation.ts
|
|
9910
|
-
const REF_PARAMETER = "mobile-push";
|
|
9911
9949
|
/**
|
|
9912
9950
|
* Consume one authenticated tap reference after the public Workspace and Session
|
|
9913
9951
|
* list baselines are ready. Return the disposal function for list subscriptions.
|
|
@@ -9918,15 +9956,16 @@ window.__ModuleLoader__.load({
|
|
|
9918
9956
|
location: window.location,
|
|
9919
9957
|
history: window.history
|
|
9920
9958
|
};
|
|
9959
|
+
const refParameter = options.parameter ?? "mobile-push";
|
|
9921
9960
|
const params = new URLSearchParams(browser.location.search);
|
|
9922
|
-
const reference = params.get(
|
|
9961
|
+
const reference = params.get(refParameter);
|
|
9923
9962
|
let disposed = false;
|
|
9924
9963
|
let consumed = false;
|
|
9925
9964
|
let resolving = false;
|
|
9926
9965
|
let opened = false;
|
|
9927
9966
|
const clearReference = () => {
|
|
9928
|
-
if (!params.has(
|
|
9929
|
-
params.delete(
|
|
9967
|
+
if (!params.has(refParameter)) return;
|
|
9968
|
+
params.delete(refParameter);
|
|
9930
9969
|
const query = params.toString();
|
|
9931
9970
|
const url = `${browser.location.pathname}${query ? `?${query}` : ""}${browser.location.hash}`;
|
|
9932
9971
|
browser.history.replaceState(null, "", url);
|
|
@@ -11412,6 +11451,111 @@ dialog.dshm-picker[open]{display:grid;place-items:center}dialog.dshm-picker::bac
|
|
|
11412
11451
|
onClick: invoke
|
|
11413
11452
|
}, state === "busy" ? copy.busy : state === "success" ? copy.reopen : state === "error" ? copy.retry : copy.action));
|
|
11414
11453
|
}
|
|
11454
|
+
function mobileBackgroundNotificationCopy(locale) {
|
|
11455
|
+
if (locale === "zh") return {
|
|
11456
|
+
title: "后台任务提醒",
|
|
11457
|
+
description: "App 页面被系统挂起后,通过可关闭的常驻连接继续接收任务完成提醒。",
|
|
11458
|
+
enabled: "关闭后台提醒",
|
|
11459
|
+
disabled: "开启后台提醒",
|
|
11460
|
+
busy: "正在处理…",
|
|
11461
|
+
error: "无法更新后台提醒;请确认任务通知权限和当前连接。"
|
|
11462
|
+
};
|
|
11463
|
+
if (locale === "it") return {
|
|
11464
|
+
title: "Promemoria in background",
|
|
11465
|
+
description: "Continua a ricevere gli avvisi quando Android sospende la pagina, tramite una connessione persistente disattivabile.",
|
|
11466
|
+
enabled: "Disattiva promemoria",
|
|
11467
|
+
disabled: "Attiva promemoria",
|
|
11468
|
+
busy: "Operazione…",
|
|
11469
|
+
error: "Impossibile aggiornare i promemoria; controlla il permesso notifiche e la connessione attiva."
|
|
11470
|
+
};
|
|
11471
|
+
return {
|
|
11472
|
+
title: "Background task reminders",
|
|
11473
|
+
description: "Keep receiving completion alerts after Android suspends the page, through a dismissible persistent connection.",
|
|
11474
|
+
enabled: "Disable background reminders",
|
|
11475
|
+
disabled: "Enable background reminders",
|
|
11476
|
+
busy: "Working…",
|
|
11477
|
+
error: "Could not update background reminders. Check notification permission and the active connection."
|
|
11478
|
+
};
|
|
11479
|
+
}
|
|
11480
|
+
/** Android-only opt-in for the foreground SSE fallback when the WebView is suspended. */
|
|
11481
|
+
function MobileBackgroundNotificationRow() {
|
|
11482
|
+
const [supported, setSupported] = (0, react.useState)(false);
|
|
11483
|
+
const [enabled, setEnabled] = (0, react.useState)(false);
|
|
11484
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
11485
|
+
const [error, setError] = (0, react.useState)(false);
|
|
11486
|
+
const generation = (0, react.useRef)(0);
|
|
11487
|
+
(0, react.useEffect)(() => {
|
|
11488
|
+
let active = true;
|
|
11489
|
+
const refresh = () => {
|
|
11490
|
+
const attempt = ++generation.current;
|
|
11491
|
+
const bridge = window.__DSH_MOBILE_NATIVE__;
|
|
11492
|
+
if (bridge === void 0) {
|
|
11493
|
+
if (active) {
|
|
11494
|
+
setSupported(false);
|
|
11495
|
+
setError(false);
|
|
11496
|
+
}
|
|
11497
|
+
return;
|
|
11498
|
+
}
|
|
11499
|
+
Promise.resolve(bridge.capabilities()).then(async (capabilities) => {
|
|
11500
|
+
const available = capabilities.includes("notification.background.get") && capabilities.includes("notification.background.set");
|
|
11501
|
+
if (!active || attempt !== generation.current) return;
|
|
11502
|
+
setSupported(available);
|
|
11503
|
+
if (!available) return;
|
|
11504
|
+
const result = await bridge.invoke("notification.background.get", {});
|
|
11505
|
+
if (!active || attempt !== generation.current) return;
|
|
11506
|
+
if (typeof result?.enabled !== "boolean") throw new Error("invalid background notification status");
|
|
11507
|
+
setEnabled(result.enabled);
|
|
11508
|
+
setError(false);
|
|
11509
|
+
}).catch(() => {
|
|
11510
|
+
if (active && attempt === generation.current) {
|
|
11511
|
+
setSupported(true);
|
|
11512
|
+
setError(true);
|
|
11513
|
+
}
|
|
11514
|
+
});
|
|
11515
|
+
};
|
|
11516
|
+
refresh();
|
|
11517
|
+
window.addEventListener("dsh-mobile-native-ready", refresh);
|
|
11518
|
+
return () => {
|
|
11519
|
+
active = false;
|
|
11520
|
+
generation.current += 1;
|
|
11521
|
+
window.removeEventListener("dsh-mobile-native-ready", refresh);
|
|
11522
|
+
};
|
|
11523
|
+
}, []);
|
|
11524
|
+
if (!supported) return null;
|
|
11525
|
+
const locale = selectedMobileControlLocale();
|
|
11526
|
+
const copy = mobileBackgroundNotificationCopy(locale);
|
|
11527
|
+
const toggle = () => {
|
|
11528
|
+
const bridge = window.__DSH_MOBILE_NATIVE__;
|
|
11529
|
+
if (bridge === void 0 || busy) return;
|
|
11530
|
+
const attempt = ++generation.current;
|
|
11531
|
+
setBusy(true);
|
|
11532
|
+
setError(false);
|
|
11533
|
+
bridge.invoke("notification.background.set", { enabled: !enabled }).then((result) => {
|
|
11534
|
+
if (attempt !== generation.current) return;
|
|
11535
|
+
const next = result?.enabled;
|
|
11536
|
+
if (typeof next !== "boolean") throw new Error("invalid background notification status");
|
|
11537
|
+
setEnabled(next);
|
|
11538
|
+
}).catch(() => {
|
|
11539
|
+
if (attempt === generation.current) setError(true);
|
|
11540
|
+
}).finally(() => {
|
|
11541
|
+
if (attempt === generation.current) setBusy(false);
|
|
11542
|
+
});
|
|
11543
|
+
};
|
|
11544
|
+
return (0, react.createElement)("div", {
|
|
11545
|
+
className: "dsh-mobile-settings_row",
|
|
11546
|
+
lang: locale
|
|
11547
|
+
}, (0, react.createElement)("div", { className: "dsh-mobile-settings_rowText" }, (0, react.createElement)("div", { className: "dsh-mobile-settings_title" }, copy.title), (0, react.createElement)("div", {
|
|
11548
|
+
className: "dsh-mobile-settings_desc",
|
|
11549
|
+
"aria-live": "polite"
|
|
11550
|
+
}, error ? copy.error : copy.description)), (0, react.createElement)("button", {
|
|
11551
|
+
type: "button",
|
|
11552
|
+
className: "dsh-mobile-settings_selector",
|
|
11553
|
+
disabled: busy,
|
|
11554
|
+
"aria-busy": busy ? "true" : void 0,
|
|
11555
|
+
"aria-pressed": enabled ? "true" : "false",
|
|
11556
|
+
onClick: toggle
|
|
11557
|
+
}, busy ? copy.busy : enabled ? copy.enabled : copy.disabled));
|
|
11558
|
+
}
|
|
11415
11559
|
const CONTROL_REQUEST_TIMEOUT_MS = 15e3;
|
|
11416
11560
|
const LONG_CONTROL_REQUEST_TIMEOUT_MS = 21e4;
|
|
11417
11561
|
const GITHUB_RELEASES_URL = "https://github.com/saya-ch/dsh-mobile/releases";
|
|
@@ -17252,7 +17396,8 @@ dialog.dshm-picker[open]{display:grid;place-items:center}dialog.dshm-picker::bac
|
|
|
17252
17396
|
kind: "done",
|
|
17253
17397
|
title: label("Attività completata", "Task finished", "任务已完成"),
|
|
17254
17398
|
body: label("Il tuo task DSH è terminato", "Your DSH task finished", "你的 DSH 任务已完成"),
|
|
17255
|
-
tag: taskCompletionTag(parsed.sessionId, parsed.turn)
|
|
17399
|
+
tag: taskCompletionTag(parsed.sessionId, parsed.turn),
|
|
17400
|
+
navigate: taskNotificationNavigate(parsed.sessionId)
|
|
17256
17401
|
});
|
|
17257
17402
|
}, () => {
|
|
17258
17403
|
fireDeviceRevoked();
|
|
@@ -17471,6 +17616,46 @@ dialog.dshm-picker[open]{display:grid;place-items:center}dialog.dshm-picker::bac
|
|
|
17471
17616
|
page.body.append(node);
|
|
17472
17617
|
view.setTimeout(() => node.remove(), 3e3);
|
|
17473
17618
|
}
|
|
17619
|
+
/** Consume the Android background service's opaque Session route on cold or warm launch. */
|
|
17620
|
+
function installTaskNotificationNavigation(ctx, page, view) {
|
|
17621
|
+
if (view.__DSH_MOBILE_FRONTEND__ !== "dedicated" || ctx.inject === void 0) return () => void 0;
|
|
17622
|
+
if (new URLSearchParams(view.location.search).get("dsh-session") === null) return () => void 0;
|
|
17623
|
+
let closed = false;
|
|
17624
|
+
let removeNavigation;
|
|
17625
|
+
const fiber = ctx.inject(mobilePushNavigationServices, (navigationContext) => {
|
|
17626
|
+
if (closed) return () => void 0;
|
|
17627
|
+
if (new URLSearchParams(view.location.search).get("dsh-session") === null) return () => void 0;
|
|
17628
|
+
const remove = installPushNavigation(navigationContext, {
|
|
17629
|
+
parameter: "dsh-session",
|
|
17630
|
+
resolve: async (value) => {
|
|
17631
|
+
const sessionId = decodeTaskNotificationNavigate(value);
|
|
17632
|
+
return sessionId === void 0 ? void 0 : {
|
|
17633
|
+
sessionId,
|
|
17634
|
+
interaction: "current"
|
|
17635
|
+
};
|
|
17636
|
+
},
|
|
17637
|
+
notify: (key) => {
|
|
17638
|
+
if (key === "session-unavailable" || key === "session-resolved") showMobilePushNavigationNotice(page, view, key);
|
|
17639
|
+
},
|
|
17640
|
+
browser: {
|
|
17641
|
+
location: view.location,
|
|
17642
|
+
history: view.history
|
|
17643
|
+
}
|
|
17644
|
+
});
|
|
17645
|
+
removeNavigation = remove;
|
|
17646
|
+
return () => {
|
|
17647
|
+
if (removeNavigation === remove) removeNavigation = void 0;
|
|
17648
|
+
remove();
|
|
17649
|
+
};
|
|
17650
|
+
});
|
|
17651
|
+
return () => {
|
|
17652
|
+
if (closed) return;
|
|
17653
|
+
closed = true;
|
|
17654
|
+
removeNavigation?.();
|
|
17655
|
+
removeNavigation = void 0;
|
|
17656
|
+
fiber.dispose();
|
|
17657
|
+
};
|
|
17658
|
+
}
|
|
17474
17659
|
/** Own the browser-only push controller, settings row, and optional authenticated tap navigation. */
|
|
17475
17660
|
function installMobilePushBrowserClient(ctx, runtime) {
|
|
17476
17661
|
const { page, view } = runtime;
|
|
@@ -17582,6 +17767,7 @@ dialog.dshm-picker[open]{display:grid;place-items:center}dialog.dshm-picker::bac
|
|
|
17582
17767
|
page: document,
|
|
17583
17768
|
view: window
|
|
17584
17769
|
}), "dsh-mobile: authenticated browser push lifecycle");
|
|
17770
|
+
ctx.effect(() => installTaskNotificationNavigation(ctx, document, window), "dsh-mobile: native task notification navigation");
|
|
17585
17771
|
ctx.effect(() => {
|
|
17586
17772
|
const desktopAdmin = isDesktopAdminSurface(location.hostname, location.search, window.__DSH_MOBILE_FRONTEND__, location.protocol);
|
|
17587
17773
|
const gatewayCustomization = ownsMobileCustomization(document.querySelector("meta[name=\"dsh-mobile-gateway\"][content=\"authenticated\"]") !== null, window.__DSH_MOBILE_FRONTEND__);
|
|
@@ -17639,7 +17825,13 @@ dialog.dshm-picker[open]{display:grid;place-items:center}dialog.dshm-picker::bac
|
|
|
17639
17825
|
id: "dsh-mobile-task-notifications",
|
|
17640
17826
|
order: 110
|
|
17641
17827
|
}, MobileTaskNotificationRow);
|
|
17828
|
+
const removeBackgroundNotifications = ctx.slots.register({
|
|
17829
|
+
name: "settings.general.item",
|
|
17830
|
+
id: "dsh-mobile-background-notifications",
|
|
17831
|
+
order: 111
|
|
17832
|
+
}, MobileBackgroundNotificationRow);
|
|
17642
17833
|
return () => {
|
|
17834
|
+
removeBackgroundNotifications();
|
|
17643
17835
|
removeTaskNotifications();
|
|
17644
17836
|
removeSwitchComputer();
|
|
17645
17837
|
removeDisplayScale();
|
|
@@ -17752,6 +17944,7 @@ dialog.dshm-picker[open]{display:grid;place-items:center}dialog.dshm-picker::bac
|
|
|
17752
17944
|
exports.installDshLanguageBoundSurface = installDshLanguageBoundSurface;
|
|
17753
17945
|
exports.installMobileNativeBack = installMobileNativeBack;
|
|
17754
17946
|
exports.installMobilePushBrowserClient = installMobilePushBrowserClient;
|
|
17947
|
+
exports.installTaskNotificationNavigation = installTaskNotificationNavigation;
|
|
17755
17948
|
exports.localizedDiagnosticEntryCopy = localizedDiagnosticEntryCopy;
|
|
17756
17949
|
exports.mobileBackBlockedMessage = mobileBackBlockedMessage;
|
|
17757
17950
|
exports.mobilePushNavigationNotice = mobilePushNavigationNotice;
|