返回 AiToEarn
appLaunch.ts
根目录 / project / aitoearn-web / src / utils / appLaunch.ts
1 /**
2 * appLaunch - App 唤起工具
3 * 通过多策略(iframe + location.href + 超时降级)唤起移动端 App
4 */
5
6 interface LaunchUrlOptions {
7 timeout?: number
8 fallbackUrl?: string
9 onFailed?: () => void
10 }
11
12 function launchUrl(url: string, options: LaunchUrlOptions = {}) {
13 const { timeout = 2500, fallbackUrl, onFailed } = options
14 let timer: ReturnType<typeof setTimeout> | null = null
15 let hidden = false
16 let cleaned = false
17
18 const cleanup = () => {
19 if (cleaned)
20 return
21
22 cleaned = true
23 document.removeEventListener('visibilitychange', onVisibilityChange)
24 window.removeEventListener('pagehide', onPageHide)
25
26 if (timer) {
27 clearTimeout(timer)
28 timer = null
29 }
30 }
31
32 const markHidden = () => {
33 hidden = true
34 cleanup()
35 }
36
37 const onVisibilityChange = () => {
38 if (document.hidden) {
39 markHidden()
40 }
41 }
42
43 const onPageHide = () => {
44 markHidden()
45 }
46
47 document.addEventListener('visibilitychange', onVisibilityChange)
48 window.addEventListener('pagehide', onPageHide)
49
50 const iframe = document.createElement('iframe')
51 iframe.style.display = 'none'
52 iframe.src = url
53 document.body.appendChild(iframe)
54 setTimeout(() => {
55 if (iframe.parentNode) {
56 iframe.parentNode.removeChild(iframe)
57 }
58 }, 1000)
59
60 setTimeout(() => {
61 if (!hidden) {
62 window.location.href = url
63 }
64 }, 200)
65
66 timer = setTimeout(() => {
67 cleanup()
68
69 if (!hidden) {
70 if (fallbackUrl) {
71 window.location.href = fallbackUrl
72 }
73 onFailed?.()
74 }
75 }, timeout)
76 }
77
78 /**
79 * 通过 API URL 唤起 App(API 会 302 重定向到 scheme URL)
80 * 多策略:iframe 唤起 + location.href 备选 + 超时降级
81 */
82 export function openApp(apiUrl: string, onFailed: () => void) {
83 launchUrl(apiUrl, { onFailed })
84 }
85
86 /**
87 * 通过 deeplink 或 scheme URL 唤起 App
88 * 适用于前端已拿到最终唤起链接的场景,如小红书分享 deeplink
89 */
90 export function openDeepLink(url: string, options: LaunchUrlOptions = {}) {
91 launchUrl(url, options)
92 }
93
93 lines TYPESCRIPT