Skip to content

Commit 7c81591

Browse files
authored
Merge pull request #175 from ASAP-Lettering/test/#174
[Test] PWA 설치 유도 기능 테스트
2 parents 33825e4 + ff77668 commit 7c81591

File tree

2 files changed

+133
-1
lines changed

2 files changed

+133
-1
lines changed

next.config.mjs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ export default withPlugins(
2020
withPWA,
2121
{
2222
pwa: {
23-
dest: 'public'
23+
dest: 'public',
24+
register: true,
25+
skipWaiting: true
2426
}
2527
}
2628
],

src/app/test/page.tsx

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
'use client';
2+
3+
import Button from '@/components/common/Button';
4+
import ConfirmModal from '@/components/common/ConfirmModal';
5+
import { theme } from '@/styles/theme';
6+
import React, { useEffect, useState } from 'react';
7+
import styled from 'styled-components';
8+
9+
declare global {
10+
interface WindowEventMap {
11+
beforeinstallprompt: BeforeInstallPromptEvent;
12+
}
13+
}
14+
15+
interface BeforeInstallPromptEvent extends Event {
16+
readonly platforms: Array<string>;
17+
readonly userChoice: Promise<{
18+
outcome: 'accepted' | 'dismissed';
19+
platform: string;
20+
}>;
21+
prompt(): Promise<void>;
22+
}
23+
24+
const page = () => {
25+
const [deferredPrompt, setDeferredPrompt] = useState(null);
26+
const [isIOS, setIsIOS] = useState(false);
27+
const [isAndroid, setIsAndroid] = useState(false);
28+
29+
const [showModal, setShowModal] = useState(false);
30+
31+
useEffect(() => {
32+
const userAgent = window.navigator.userAgent.toLowerCase();
33+
const isIOSDevice = /iphone|ipad|ipod/.test(userAgent);
34+
const isAndroidDevice = /android/.test(userAgent);
35+
36+
setIsIOS(isIOSDevice);
37+
setIsAndroid(isAndroidDevice);
38+
39+
// Android에서만 beforeinstallprompt 이벤트 처리
40+
if (isAndroidDevice) {
41+
const handler = (e: any) => {
42+
console.log('🔥 beforeinstallprompt 발생');
43+
e.preventDefault();
44+
setDeferredPrompt(e);
45+
};
46+
47+
window.addEventListener('beforeinstallprompt', handler);
48+
return () => {
49+
window.removeEventListener('beforeinstallprompt', handler);
50+
};
51+
}
52+
}, []);
53+
54+
const handleInstallClick = async () => {
55+
if (isAndroid && deferredPrompt) {
56+
deferredPrompt.prompt();
57+
const { outcome } = await deferredPrompt.userChoice;
58+
console.log('Android 사용자 선택:', outcome);
59+
setDeferredPrompt(null);
60+
setShowModal(false);
61+
} else if (isIOS) {
62+
// iOS는 안내만
63+
alert(
64+
'iPhone 사용자는 Safari에서 공유 버튼을 눌러 [홈 화면에 추가]를 선택해주세요!'
65+
);
66+
setShowModal(false);
67+
} else {
68+
alert('설치 기능이 현재 환경에서 지원되지 않습니다.');
69+
setShowModal(false);
70+
}
71+
};
72+
73+
const handleShowModal = () => {
74+
if (isAndroid && deferredPrompt) {
75+
setShowModal(true);
76+
} else if (isIOS) {
77+
setShowModal(true);
78+
} else {
79+
alert('브라우저가 아직 설치를 허용하지 않았습니다.');
80+
}
81+
};
82+
83+
return (
84+
<Container>
85+
<Title>PWA 설치 유도 TEST</Title>
86+
<Button
87+
buttonType="primary"
88+
text="앱 설치하기"
89+
onClick={handleShowModal}
90+
/>
91+
{showModal && (
92+
<ConfirmModal
93+
title="PWA 설치하기"
94+
sub={
95+
isIOS
96+
? 'Safari 공유 버튼을 눌러 [홈 화면에 추가]를 선택해주세요.'
97+
: '홈 화면에 추가하시겠어요?'
98+
}
99+
confirmText={isIOS ? '알겠습니다' : '설치하기'}
100+
cancelText="취소"
101+
onConfirm={handleInstallClick}
102+
onCancel={() => setShowModal(false)}
103+
/>
104+
)}
105+
</Container>
106+
);
107+
};
108+
109+
export default page;
110+
111+
const Container = styled.div`
112+
display: flex;
113+
box-sizing: border-box;
114+
padding: 100px 30px;
115+
height: 100vh;
116+
flex-direction: column;
117+
justify-content: space-between;
118+
background-image: url('/assets/login/login_bg.png');
119+
background-size: cover;
120+
background-position: center;
121+
background-repeat: no-repeat;
122+
-webkit-scrollbar {
123+
display: none;
124+
}
125+
`;
126+
127+
const Title = styled.h1`
128+
color: ${theme.colors.white};
129+
text-align: center;
130+
`;

0 commit comments

Comments
 (0)