mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 09:33:46 +00:00
fix(connection): stop ERR_UNKNOWN_URL_SCHEME when opening app deep links on mobile
Telegram bug #654272: opening the connection app link (immediate-open / connect button) showed a full-page net::ERR_UNKNOWN_URL_SCHEME on Android and silently failed on iOS, while working on desktop. Cause: a programmatic top-level navigation to a custom scheme (happ://, v2rayng://, …) via window.location.href is rendered as a full-page error inside in-app WebViews (Telegram/Yandex) on Android and does nothing on iOS — also wiping the fallback UI. Add openAppScheme(): http(s) navigate normally; custom schemes launch via a hidden, contained iframe so a failed launch never replaces the page — the app opens if installed, otherwise the manual 'Open app' link stays usable (a user tap is the reliable trigger). Applied in DeepLinkRedirect.tsx, Connection.tsx and the static public/miniapp/redirect.html (which now also surfaces the manual button immediately instead of after 2s).
This commit is contained in:
39
src/utils/openAppScheme.ts
Normal file
39
src/utils/openAppScheme.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Launch a custom-scheme app deep link (happ://, v2rayng://, vless://, …) without
|
||||
* crashing the page inside in-app browsers.
|
||||
*
|
||||
* Why not `window.location.href = scheme`: a programmatic top-level navigation to a
|
||||
* scheme the WebView can't resolve renders a full-page error — on Android in-app
|
||||
* browsers (Telegram/Yandex/…) `net::ERR_UNKNOWN_URL_SCHEME`, on iOS it silently does
|
||||
* nothing — which destroys the fallback UI (Telegram bug #654272). A hidden <iframe>
|
||||
* navigation is contained: if the app is installed the OS intercepts it; if not, the
|
||||
* failure stays inside the (invisible) frame and our page — with its manual "Open app"
|
||||
* link — survives so the user can tap it (a real user gesture is the reliable trigger).
|
||||
*
|
||||
* http(s) links are normal navigations and are passed straight to location.href.
|
||||
*/
|
||||
export function openAppScheme(url: string): void {
|
||||
const isHttp = /^https?:\/\//i.test(url);
|
||||
if (isHttp) {
|
||||
window.location.href = url;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.style.display = 'none';
|
||||
iframe.src = url;
|
||||
document.body.appendChild(iframe);
|
||||
window.setTimeout(() => {
|
||||
try {
|
||||
iframe.remove();
|
||||
} catch {
|
||||
/* already detached */
|
||||
}
|
||||
}, 2000);
|
||||
} catch {
|
||||
// iframe creation blocked (very old/locked-down WebView) — fall back to direct
|
||||
// navigation. Worst case this shows the same error the iframe avoided, never worse.
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user