fix(ui): route external links out of the Android VK WebView

The Android VK client's WebView ignores target=_blank and navigates the
Mini App's own window to the target, stranding the player outside the
game with no way back (the dictionary lookup, About/Feedback links, the
ad banner and the bot-link modal fallbacks). vk-bridge 3.x has no method
to open an external URL, so external links are routed through VK's own
leave-VK redirect (vk.com/away.php), which the client intercepts
natively and hands to the system browser.

onExternalLinkClick moves from lib/telegram to a new lib/links that
composes the Telegram and VK routers; iOS and desktop VK open _blank
correctly and are left alone.
This commit is contained in:
Ilia Denisov
2026-07-02 00:09:52 +02:00
parent c864147982
commit db17287113
11 changed files with 200 additions and 25 deletions
+31
View File
@@ -0,0 +1,31 @@
// Platform-aware external-link opening. Both Mini App hosts mishandle a plain target=_blank
// anchor: Telegram shows the WebView's generic "open this link?" confirmation, and the Android VK
// client navigates the app's own WebView to the target with no way back to the game. The helpers
// below route an external URL through the platform's escape hatch (Telegram's openLink, VK's
// away.php redirect) and leave the anchor's own navigation / window.open in effect elsewhere.
import { routeExternalLinkInTelegram } from './telegram';
import { routeExternalLinkInVK, vkOpenExternalUrl } from './vk';
/**
* onExternalLinkClick is the anchor click handler for external links. It resolves the clicked
* anchor with closest(), so it works both attached directly on an <a> and delegated on a container
* that renders links (e.g. {@html} markdown). Attach it as onclick on an external link or its
* container; outside Telegram and VK it is a no-op and the anchor's own target=_blank handles the
* click.
*/
export function onExternalLinkClick(e: MouseEvent): void {
const a = (e.target as HTMLElement | null)?.closest('a');
if (!a) return;
if (routeExternalLinkInTelegram(a) || routeExternalLinkInVK(a)) e.preventDefault();
}
/**
* openExternalUrl opens an external URL from code (no anchor to click): through VK's external
* redirect inside the Android VK client, else a plain new tab. Telegram callers try their native
* opener (telegramOpenLink) first and use this as the fallback.
*/
export function openExternalUrl(url: string): void {
if (vkOpenExternalUrl(url)) return;
if (typeof window !== 'undefined') window.open(url, '_blank');
}