'use client'; /** * FCM 푸시 알림 훅 * * Capacitor 네이티브 앱에서 FCM 푸시 알림을 처리합니다. * - 로그인 상태에서 자동으로 FCM 초기화 * - 포그라운드 알림을 sonner 토스트로 표시 * - 로그아웃 시 FCM 토큰 해제 * * @example * ```tsx * // FCMProvider에서 사용 * function FCMProvider({ children }) { * useFCM(); * return <>{children}; * } * ``` */ import { useEffect, useRef, useCallback } from 'react'; import { toast } from 'sonner'; import { initializeFCM, unregisterFCMToken, isCapacitorNative, getToastTypeByNotificationType, type FCMNotification, type ToastType, } from '@/lib/capacitor/fcm'; import { hasAuthToken } from '@/lib/api/auth-headers'; export function useFCM() { const initialized = useRef(false); /** * 포그라운드 알림 핸들러 (sonner 토스트) */ const handleForegroundNotification = useCallback((notification: FCMNotification) => { const { title, body, data } = notification; const type = data?.type; const url = data?.url; // 타입별 토스트 스타일 결정 const toastType: ToastType = getToastTypeByNotificationType(type); // 토스트 옵션 const toastOptions = { description: body, duration: 5000, action: url ? { label: '보기', onClick: () => { window.location.href = url; }, } : undefined, }; // 타입별 토스트 표시 const toastTitle = title || '알림'; switch (toastType) { case 'error': toast.error(toastTitle, toastOptions); break; case 'warning': toast.warning(toastTitle, toastOptions); break; case 'success': toast.success(toastTitle, toastOptions); break; default: toast.info(toastTitle, toastOptions); } }, []); /** * FCM 초기화 */ useEffect(() => { // 네이티브 환경이 아니면 무시 if (!isCapacitorNative()) { console.log('[useFCM] Not in native environment, skipping'); return; } // 이미 초기화됐으면 무시 if (initialized.current) { return; } // 로그인 상태가 아니면 무시 if (!hasAuthToken()) { console.log('[useFCM] No auth token, skipping FCM initialization'); return; } // FCM 초기화 initialized.current = true; console.log('[useFCM] Initializing FCM...'); initializeFCM(handleForegroundNotification).then((success) => { if (success) { console.log('[useFCM] FCM initialized successfully'); } else { console.log('[useFCM] FCM initialization failed or skipped'); initialized.current = false; } }); }, [handleForegroundNotification]); /** * FCM 토큰 해제 (로그아웃 시 호출) */ const cleanup = useCallback(async () => { console.log('[useFCM] Cleaning up FCM...'); await unregisterFCMToken(); initialized.current = false; }, []); return { cleanup }; } /** * FCM cleanup 함수만 반환하는 훅 * (로그아웃 로직에서 사용) */ export function useFCMCleanup() { const cleanup = useCallback(async () => { if (!isCapacitorNative()) return; await unregisterFCMToken(); }, []); return { cleanup }; }