From d60cd3fd998ee443077fd21f5192dc1c0f48a256 Mon Sep 17 00:00:00 2001 From: evermake Date: Thu, 15 Jan 2026 15:34:37 +0500 Subject: [PATCH] implement links opening --- packages/mini-app/src/Links.ts | 91 ++++++++++++++++++++++++++++++++++ packages/mini-app/src/index.ts | 1 + 2 files changed, 92 insertions(+) create mode 100644 packages/mini-app/src/Links.ts diff --git a/packages/mini-app/src/Links.ts b/packages/mini-app/src/Links.ts new file mode 100644 index 0000000..ff437e5 --- /dev/null +++ b/packages/mini-app/src/Links.ts @@ -0,0 +1,91 @@ +import type { Bridge } from './Bridge.ts' +import type { OutgoingEventMap } from './Events.ts' + +export interface Links { + openLink: ( + url: string | URL, + options?: { + tryInstantView?: boolean + tryBrowser?: + | 'chrome' + | 'firefox' + | 'edge' + | 'opera' + | 'opera-mini' + | 'brave' + | 'duckduckgo' + | 'samsung' + | 'vivaldi' + | 'kiwi' + | 'uc' + | 'tor' + }, + ) => void + openTelegramLink: ( + url: string | URL, + options?: { + force_request?: boolean + }, + ) => void +} + +export interface InitOptions { + bridge: Bridge + isIframe: boolean +} + +export const init = ({ + bridge, + isIframe, +}: InitOptions): Links => { + const links: Links = { + openLink: (url_, options = {}) => { + const url = new URL(url_) + const params: OutgoingEventMap['open_link'] = { + url: url.toString(), + } + if (options.tryInstantView) { + params.try_instant_view = true + } + if (options.tryBrowser) { + params.try_browser = options.tryBrowser + } + bridge.emit('open_link', params) + }, + openTelegramLink: (url_, options = {}) => { + const url = new URL(url_) + const params: OutgoingEventMap['open_tg_link'] = { + path_full: url.pathname + url.search, + } + if (options.force_request) { + params.force_request = true + } + bridge.emit('open_tg_link', params) + }, + } + if (isIframe) { + document.addEventListener('click', (event) => { + if (event.metaKey || event.ctrlKey) { + return + } + let el = event.target as any + if (el == null) { + return + } + while (el.tagName !== 'A' && el.parentNode) { + el = el.parentNode + } + const anchor = el as HTMLAnchorElement + if ( + anchor.tagName === 'A' && + anchor.target !== '_blank' && + (anchor.protocol === 'http:' || anchor.protocol === 'https:') && + anchor.hostname === 't.me' + ) { + links.openTelegramLink(anchor.href) + event.preventDefault() + } + }) + } + return links +} diff --git a/packages/mini-app/src/index.ts b/packages/mini-app/src/index.ts index 5717840..b975ab3 100644 --- a/packages/mini-app/src/index.ts +++ b/packages/mini-app/src/index.ts @@ -6,6 +6,7 @@ export * as Fullscreen from './Fullscreen.ts' export * as Haptic from './Haptic.ts' export * as LaunchParams from './LaunchParams.ts' export * as Lifecycle from './Lifecycle.ts' +export * as Links from './Links.ts' export * as MainButton from './MainButton.ts' export * as SecondaryButton from './SecondaryButton.ts' export * as SessionStorage from './SessionStorage.ts'