Skip to content

Commit dd7afbc

Browse files
committed
fix: ios 딥링크 로직 수정
1 parent c2fceef commit dd7afbc

File tree

1 file changed

+53
-47
lines changed

1 file changed

+53
-47
lines changed

apps/tuk-web/src/app/invite/meet/[meetId]/src/components/InviteProposal.tsx

Lines changed: 53 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import SkeletonGuard from '@/shared/components/SkeletonGuard';
1212
import { useParam } from '@/shared/hooks/useParam';
1313

1414
// === Deep Link: 강화 폴백 유틸 시작 ===
15-
const IOS_STORE_URL =
15+
const IOS_STORE_URL_WEB =
1616
'https://apps.apple.com/kr/app/%ED%88%AD-%EB%A7%8C%EB%82%8C%EC%9D%84-%EB%84%8C%EC%A7%80%EC%8B%9C/id6749781762';
17+
const IOS_STORE_URL_APPS = 'itms-apps://itunes.apple.com/app/id6749781762'; // App Store 앱 직접 오픈
1718
const ANDROID_STORE_URL = 'https://play.google.com/store/apps/details?id=com.plottwist.tuk';
1819

1920
function buildAndroidIntent(path: string, playUrl: string) {
@@ -31,63 +32,68 @@ function buildAndroidIntent(path: string, playUrl: string) {
3132
function openProposalInApp(proposalId: number | string) {
3233
const ua = navigator.userAgent.toLowerCase();
3334
const isAndroid = ua.includes('android');
34-
35-
// 인앱 브라우저(대략) 감지 — 카톡/인스타 등
36-
const isInApp = /\b(kakaotalk|instagram|line|fb_iab|fbav|twitter|naver(inapp)?|daumapps)\b/.test(
37-
ua
38-
);
35+
const isIOS = /iphone|ipad|ipod/.test(ua);
3936

4037
// 공통 스킴 (앱에서 열릴 실제 진입 위치)
41-
const iosScheme = `tuk-app://tuk/proposal-detail/${encodeURIComponent(String(proposalId))}`;
42-
const androidPath = `tuk/proposal-detail/${encodeURIComponent(String(proposalId))}`;
38+
const schemeUrl = `tuk-app://tuk/proposal-detail/${encodeURIComponent(String(proposalId))}`;
4339

44-
// Android: 가능하면 intent:// 로 한 방에 폴백 자동 처리
4540
if (isAndroid) {
41+
// 안드로이드는 기존 intent 유지 (정상 동작 중)
42+
const androidPath = `tuk/proposal-detail/${encodeURIComponent(String(proposalId))}`;
4643
const intentUrl = buildAndroidIntent(androidPath, ANDROID_STORE_URL);
47-
// 일부 인앱 브라우저는 intent 처리에 제약이 있어도, 시도 → 스토어 폴백은 작동
4844
window.location.href = intentUrl;
4945
return;
5046
}
5147

52-
// iOS (및 기타): 스킴 시도 → 전환 신호 없으면 스토어로 replace
53-
const fallbackDelayMs = 1700; // 1500~1800 권장
54-
let timer: number | null = null;
55-
56-
const cleanup = () => {
57-
if (timer) {
58-
window.clearTimeout(timer);
59-
timer = null;
60-
}
61-
document.removeEventListener('visibilitychange', onHide, true);
62-
window.removeEventListener('pagehide', onHide, true);
63-
window.removeEventListener('blur', onHide, true);
64-
};
65-
const onHide = () => {
66-
// 앱으로 전환되면 페이지가 숨김/이탈/블러됨 → 타이머 취소
67-
cleanup();
68-
};
69-
70-
document.addEventListener('visibilitychange', onHide, true);
71-
window.addEventListener('pagehide', onHide, true);
72-
window.addEventListener('blur', onHide, true);
73-
74-
// 인앱 브라우저일 때 커스텀 스킴이 막히는 케이스가 흔하지만
75-
// 그래도 한번 시도 후 폴백(UX 유지)
76-
try {
77-
window.location.href = iosScheme;
78-
} catch {
79-
/* empty */
48+
if (isIOS) {
49+
// iOS: 히든 iframe으로 조용히 스킴 시도 → 실패 시 App Store 앱(itms-apps://) 폴백
50+
const fallbackDelayMs = 1500; // 1300~1700 권장
51+
let timer: number | null = null;
52+
53+
const cleanup = () => {
54+
if (timer) {
55+
window.clearTimeout(timer);
56+
timer = null;
57+
}
58+
document.removeEventListener('visibilitychange', onHide, true);
59+
window.removeEventListener('pagehide', onHide, true);
60+
window.removeEventListener('blur', onHide, true);
61+
const iframe = document.getElementById('__dl_iframe__');
62+
if (iframe && iframe.parentNode) iframe.parentNode.removeChild(iframe);
63+
};
64+
const onHide = () => {
65+
// 앱으로 전환되면 페이지가 숨김/이탈/블러됨 → 타이머 취소
66+
cleanup();
67+
};
68+
69+
document.addEventListener('visibilitychange', onHide, true);
70+
window.addEventListener('pagehide', onHide, true);
71+
window.addEventListener('blur', onHide, true);
72+
73+
// 히든 iframe으로 스킴 시도 (미설치 시 알럿 없이 조용히 실패)
74+
const iframe = document.createElement('iframe');
75+
iframe.style.display = 'none';
76+
iframe.id = '__dl_iframe__';
77+
iframe.src = schemeUrl;
78+
document.body.appendChild(iframe);
79+
80+
// 전환이 없으면 App Store 앱을 직접 오픈 (itms-apps://)
81+
timer = window.setTimeout(() => {
82+
try {
83+
window.location.replace(IOS_STORE_URL_APPS);
84+
} catch {
85+
// 혹시 itms-apps가 막히면 웹 스토어로 폴백
86+
window.location.replace(IOS_STORE_URL_WEB);
87+
} finally {
88+
cleanup();
89+
}
90+
}, fallbackDelayMs);
91+
92+
return;
8093
}
8194

82-
timer = window.setTimeout(
83-
() => {
84-
// 전환 신호 없으면 미설치/차단으로 판단 → 스토어로 이동
85-
// replace를 써서 '뒤로 가기' 시 빈 페이지/루프 방지
86-
window.location.replace(IOS_STORE_URL);
87-
cleanup();
88-
},
89-
isInApp ? 1200 : fallbackDelayMs
90-
); // 인앱 브라우저는 약간 더 짧게
95+
// 기타 환경(데스크톱 등)은 앱 스토어 웹 페이지로
96+
window.location.href = IOS_STORE_URL_WEB;
9197
}
9298
// === Deep Link: 강화 폴백 유틸 끝 ===
9399

0 commit comments

Comments
 (0)