fix: keep deeplink gateway open during app prompt

This commit is contained in:
3252a8
2026-06-01 20:34:49 +03:00
parent 687fc03e8c
commit 5b19ba2c2f
4 changed files with 17 additions and 6 deletions
@@ -109,6 +109,8 @@
let attempted = false; let attempted = false;
let pageLeft = false; let pageLeft = false;
let state = "opening"; let state = "opening";
let closeAttemptTimer = null;
const CLOSE_ATTEMPT_DELAY_MS = 2500;
function hasControlChars(value) { function hasControlChars(value) {
return Array.from(String(value || "")).some((char) => { return Array.from(String(value || "")).some((char) => {
@@ -167,7 +169,10 @@
function markDone() { function markDone() {
if (state === "done" || isUnsafe) return; if (state === "done" || isUnsafe) return;
render("done"); render("done");
window.setTimeout(tryCloseWindow, 120); if (closeAttemptTimer) window.clearTimeout(closeAttemptTimer);
closeAttemptTimer = window.setTimeout(() => {
if (pageLeft || document.hidden) tryCloseWindow();
}, CLOSE_ATTEMPT_DELAY_MS);
} }
function notePageLeft() { function notePageLeft() {
@@ -201,7 +206,6 @@
render("done"); render("done");
}); });
window.addEventListener("pagehide", notePageLeft); window.addEventListener("pagehide", notePageLeft);
window.addEventListener("blur", notePageLeft);
document.addEventListener("visibilitychange", () => { document.addEventListener("visibilitychange", () => {
if (!attempted) return; if (!attempted) return;
if (document.hidden) { if (document.hidden) {
@@ -6,7 +6,7 @@
const AUTO_OPEN_DELAY_MS = 80; const AUTO_OPEN_DELAY_MS = 80;
const MANUAL_STATE_DELAY_MS = 1600; const MANUAL_STATE_DELAY_MS = 1600;
const DONE_STATE_DELAY_MS = 900; const DONE_STATE_DELAY_MS = 900;
const CLOSE_ATTEMPT_DELAY_MS = 120; const CLOSE_ATTEMPT_DELAY_MS = 2500;
export let brand = {}; export let brand = {};
export let appLaunchTarget = ""; export let appLaunchTarget = "";
@@ -54,7 +54,6 @@
autoOpenTimer = window.setTimeout(openTarget, AUTO_OPEN_DELAY_MS); autoOpenTimer = window.setTimeout(openTarget, AUTO_OPEN_DELAY_MS);
window.addEventListener("pagehide", notePageLeft); window.addEventListener("pagehide", notePageLeft);
window.addEventListener("blur", notePageLeft);
document.addEventListener("visibilitychange", handleVisibilityChange); document.addEventListener("visibilitychange", handleVisibilityChange);
return () => { return () => {
@@ -63,7 +62,6 @@
clearTimer(doneStateTimer); clearTimer(doneStateTimer);
clearTimer(closeAttemptTimer); clearTimer(closeAttemptTimer);
window.removeEventListener("pagehide", notePageLeft); window.removeEventListener("pagehide", notePageLeft);
window.removeEventListener("blur", notePageLeft);
document.removeEventListener("visibilitychange", handleVisibilityChange); document.removeEventListener("visibilitychange", handleVisibilityChange);
}; };
}); });
@@ -91,7 +89,9 @@
if (!attempted || state === "done" || !activeTarget) return; if (!attempted || state === "done" || !activeTarget) return;
state = "done"; state = "done";
clearTimer(closeAttemptTimer); clearTimer(closeAttemptTimer);
closeAttemptTimer = window.setTimeout(tryCloseWindow, CLOSE_ATTEMPT_DELAY_MS); closeAttemptTimer = window.setTimeout(() => {
if (pageLeft || document.hidden) tryCloseWindow();
}, CLOSE_ATTEMPT_DELAY_MS);
} }
function notePageLeft() { function notePageLeft() {
+4
View File
@@ -296,6 +296,10 @@ class WebAppRouteContractTests(unittest.TestCase):
self.assertIn("URLSearchParams", response.text) self.assertIn("URLSearchParams", response.text)
self.assertIn("Settings added", response.text) self.assertIn("Settings added", response.text)
self.assertIn("window.close()", response.text) self.assertIn("window.close()", response.text)
self.assertNotIn('window.addEventListener("blur", notePageLeft)', response.text)
self.assertNotIn("window.setTimeout(tryCloseWindow, 120)", response.text)
self.assertIn("const CLOSE_ATTEMPT_DELAY_MS = 2500", response.text)
self.assertIn("if (pageLeft || document.hidden) tryCloseWindow();", response.text)
self.assertIn(r"/^(?:javascript|data|vbscript|https?):/i", response.text) self.assertIn(r"/^(?:javascript|data|vbscript|https?):/i", response.text)
def test_app_deeplink_gateway_uses_i18n_template(self): def test_app_deeplink_gateway_uses_i18n_template(self):
+3
View File
@@ -44,6 +44,9 @@ def test_open_app_route_uses_fallback_screen_without_auth_flow():
assert "AppLaunchScreen" in app_source assert "AppLaunchScreen" in app_source
assert 'mode = isAppLaunchRoute ? "appLaunch"' in app_source assert 'mode = isAppLaunchRoute ? "appLaunch"' in app_source
assert "window.close()" in screen_source assert "window.close()" in screen_source
assert 'window.addEventListener("blur", notePageLeft)' not in screen_source
assert "CLOSE_ATTEMPT_DELAY_MS = 2500" in screen_source
assert "if (pageLeft || document.hidden) tryCloseWindow();" in screen_source
launch_guard_pos = app_source.index("if (isAppLaunchRoute) return;") launch_guard_pos = app_source.index("if (isAppLaunchRoute) return;")
boot_pos = app_source.index("boot();", launch_guard_pos) boot_pos = app_source.index("boot();", launch_guard_pos)