fix(push-optin): 삼성 인터넷 지원 + ArrayBuffer applicationServerKey
원인 1: applicationServerKey 타입 호환성 - Samsung Internet 은 Uint8Array 거부, ArrayBuffer 만 허용 (Chrome 은 둘 다 OK) - urlBase64ToUint8Array(publicKey).buffer 로 ArrayBuffer 명시 전달 원인 2: 사용자 환경별 안내 부재 - userAgent 의 SamsungBrowser 감지하여 isSamsungBrowser 분기 추가 - denied 모달에 삼성 인터넷 전용 가이드: 메뉴(≡) → 설정 → 사이트 권한 → 알림 → momotogether.com 허용 - 카드 하단 환경 진단에 '삼성 인터넷' / '안드로이드(Chrome)' 구분 표시 원인 3: 푸시 구독 실패 메시지 모호 - pushManager.subscribe 에러 메시지에 사이트 권한 차단 가능성 힌트 추가 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -92,12 +92,21 @@ export function PushOptIn({ variant = "compact" }: PushOptInProps) {
|
||||
const { publicKey } = await res.json();
|
||||
if (!publicKey) throw new Error("서버가 VAPID 공개키를 반환하지 않았습니다.");
|
||||
try {
|
||||
// Samsung Internet 은 ArrayBuffer 만 받음 (Uint8Array 그대로 넣으면 거부).
|
||||
// Chrome 도 ArrayBuffer 받으므로 .buffer 로 통일.
|
||||
const keyBuf = urlBase64ToUint8Array(publicKey).buffer as ArrayBuffer;
|
||||
sub = await reg.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: urlBase64ToUint8Array(publicKey) as BufferSource,
|
||||
applicationServerKey: keyBuf,
|
||||
});
|
||||
} catch (e) {
|
||||
throw new Error(`푸시 구독 실패: ${(e as Error).message ?? e}`);
|
||||
const msg = (e as Error).message ?? String(e);
|
||||
// Samsung Internet 특유 메시지 변환
|
||||
let hint = "";
|
||||
if (/abort|denied|NotAllowed/i.test(msg)) {
|
||||
hint = " (브라우저 설정에서 알림 차단됨 가능성 — 사이트 권한 확인)";
|
||||
}
|
||||
throw new Error(`푸시 구독 실패: ${msg}${hint}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,10 +303,11 @@ export function PushOptIn({ variant = "compact" }: PushOptInProps) {
|
||||
}
|
||||
|
||||
// === card 변형 (회원정보 페이지) ===
|
||||
// denied 환경 감지 — TWA 앱은 안드로이드 OS 설정, 브라우저는 사이트 설정에서 풀어야
|
||||
// denied 환경 감지 — TWA / Samsung Internet / Chrome / iOS 별 안내 분기
|
||||
const ua = typeof navigator !== "undefined" ? navigator.userAgent : "";
|
||||
const isAndroid = /Android/i.test(ua);
|
||||
const isiOS = /iPhone|iPad|iPod/i.test(ua);
|
||||
const isSamsungBrowser = /SamsungBrowser/i.test(ua);
|
||||
const isTWA = isAndroid && (/wv|; ?Trusted Web Activity/i.test(ua) || (typeof document !== "undefined" && (document.referrer ?? "").startsWith("android-app://")));
|
||||
|
||||
return (
|
||||
@@ -330,7 +340,16 @@ export function PushOptIn({ variant = "compact" }: PushOptInProps) {
|
||||
<div className="font-bold text-rose-700 inline-flex items-center gap-1">
|
||||
<AlertCircle size={13} /> 알림 권한이 차단된 상태입니다 — 직접 풀어주세요
|
||||
</div>
|
||||
{isTWA || isAndroid ? (
|
||||
{isSamsungBrowser ? (
|
||||
<ol className="list-decimal list-inside leading-relaxed space-y-0.5 text-slate-600 pl-1">
|
||||
<li><b>삼성 인터넷</b> 앱 → 우측 하단 <b>≡ (메뉴)</b> → <b>설정</b></li>
|
||||
<li><b>사이트 및 다운로드</b> → <b>사이트 권한</b> → <b>알림</b></li>
|
||||
<li><b>차단됨</b> 목록에서 <b>momotogether.com</b> 찾기 → <b>삭제</b> 또는 <b>허용</b></li>
|
||||
<li>또는 위쪽 <b>모든 사이트 보기</b> → momotogether.com → 알림 → 허용</li>
|
||||
<li>모모유통 페이지로 돌아와 새로고침 후 토글 다시</li>
|
||||
<li>그래도 안 되면: 삼성 인터넷 앱 설정 → 개인정보 → <b>인터넷 데이터 삭제</b> → 쿠키와 사이트 데이터 ✓ → 삭제</li>
|
||||
</ol>
|
||||
) : isTWA || isAndroid ? (
|
||||
<ol className="list-decimal list-inside leading-relaxed space-y-0.5 text-slate-600 pl-1">
|
||||
<li>안드로이드 <b>설정</b> 앱을 엽니다</li>
|
||||
<li><b>앱 → 모모유통</b> (또는 브라우저 이름) → <b>알림</b></li>
|
||||
@@ -362,7 +381,7 @@ export function PushOptIn({ variant = "compact" }: PushOptInProps) {
|
||||
진단 · 권한: <b className={denied ? "text-rose-500" : "text-slate-600"}>{typeof Notification !== "undefined" ? Notification.permission : "?"}</b>
|
||||
{" · "}보안: <b className={httpsOK ? "text-emerald-600" : "text-rose-500"}>{httpsOK ? "OK" : "NO"}</b>
|
||||
{" · "}SW: <b>{"serviceWorker" in (typeof navigator !== "undefined" ? navigator : ({} as Navigator)) ? "지원" : "미지원"}</b>
|
||||
{" · "}환경: <b>{isTWA ? "TWA앱" : isAndroid ? "안드로이드" : isiOS ? "iOS" : "데스크탑/기타"}</b>
|
||||
{" · "}환경: <b>{isTWA ? "TWA앱" : isSamsungBrowser ? "삼성 인터넷" : isAndroid ? "안드로이드(Chrome)" : isiOS ? "iOS" : "데스크탑/기타"}</b>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user