import { useState, useEffect, useCallback } from 'react'; import { appBridge } from '@/utils/appBridge'; import { DeviceInfo, ShareContent } from '@/types'; import { LoginResponse } from '@/entities/user/model/types'; interface UseAppBridgeReturn { isNativeEnvironment: boolean; isAndroid: boolean; isIOS: boolean; deviceInfo: DeviceInfo | null; // 네비게이션 navigateBack: () => Promise; navigateTo: (path: string) => Promise; navigateToLogin: () => Promise; closeWebView: () => Promise; // 알림 showToast: (message: string, duration?: number) => Promise; showAlert: (title: string, message: string) => Promise; showConfirm: (title: string, message: string) => Promise; // 저장소 setStorage: (key: string, value: unknown) => Promise; // getStorage: (key: string) => Promise; removeStorage: (key: string) => Promise; /* // 미디어 openCamera: (options?: { quality?: number; allowEdit?: boolean }) => Promise; openGallery: (options?: { multiple?: boolean; maxCount?: number }) => Promise; // 위치 getLocation: (options?: { enableHighAccuracy?: boolean; timeout?: number }) => Promise; // 연락처 getContacts: () => Promise; */ // 공유 shareContent: (content: ShareContent) => Promise; // 로그아웃 logout: () => Promise; // 토큰 요청 requestToken: () => Promise; requestRefreshToken: () => Promise; // 간편 인증 등록 registerBiometric: () => Promise; // 간편 인증 등록 팝업 열기 openBiometricRegistrationPopup: () => Promise; // 간편 인증 등록 팝업 닫기 closeBiometricRegistrationPopup: () => Promise; // 푸시 알림 권한 확인 isPushNotificationEnabled: () => Promise; // 앱 설정 화면 열기 openAppSettings: () => Promise; } export const useAppBridge = (): UseAppBridgeReturn => { const [deviceInfo, setDeviceInfo] = useState(null); const isNativeEnvironment = appBridge.isNativeEnvironment(); const isAndroid = appBridge.isAndroid(); const isIOS = appBridge.isIOS(); useEffect(() => { if (isNativeEnvironment) { appBridge.safeCall( () => appBridge.getDeviceInfo(), undefined, (error) => console.warn('Failed to get device info:', error) ).then(info => { if (info) setDeviceInfo(info); }); } }, [isNativeEnvironment]); const navigateBack = useCallback(async (): Promise => { if (!isNativeEnvironment) { window.history.back(); return; } return appBridge.safeCall(() => appBridge.navigateBack()); }, [isNativeEnvironment]); const navigateTo = useCallback(async (path: string): Promise => { if (!isNativeEnvironment) { window.location.href = path; return; } return appBridge.safeCall(() => appBridge.navigateTo(path)); }, [isNativeEnvironment]); const closeWebView = useCallback(async (): Promise => { if (!isNativeEnvironment) { window.close(); return; } return appBridge.safeCall(() => appBridge.closeWebView()); }, [isNativeEnvironment]); const navigateToLogin = useCallback(async (): Promise => { if (!isNativeEnvironment) { // 웹 환경에서는 로그인 페이지로 이동 window.location.href = '/login'; return; } // 네이티브 환경에서는 로그인 화면으로 이동 return appBridge.safeCall(() => appBridge.navigateTo('/login')); }, [isNativeEnvironment]); const showToast = useCallback(async (message: string, duration = 3000): Promise => { if (!isNativeEnvironment) { // 웹 환경에서는 간단한 토스트 메시지 구현 const toast = document.createElement('div'); toast.className = 'fixed top-4 right-4 bg-gray-800 text-white px-4 py-2 rounded-md z-50 animate-fade-in'; toast.textContent = message; document.body.appendChild(toast); setTimeout(() => { document.body.removeChild(toast); }, duration); return; } return appBridge.safeCall(() => appBridge.showToast(message, duration)); }, [isNativeEnvironment]); const showAlert = useCallback(async (title: string, message: string): Promise => { if (!isNativeEnvironment) { alert(`${title}\n\n${message}`); return; } return appBridge.safeCall(() => appBridge.showAlert(title, message)); }, [isNativeEnvironment]); const showConfirm = useCallback(async (title: string, message: string): Promise => { if (!isNativeEnvironment) { return confirm(`${title}\n\n${message}`); } const result = await appBridge.safeCall(() => appBridge.showConfirm(title, message), false); return result || false; }, [isNativeEnvironment]); const setStorage = useCallback(async (key: string, value: unknown): Promise => { if (!isNativeEnvironment) { localStorage.setItem(key, JSON.stringify(value)); return; } return appBridge.safeCall(() => appBridge.setStorage(key, value)); }, [isNativeEnvironment]); const removeStorage = useCallback(async (key: string): Promise => { if (!isNativeEnvironment) { localStorage.removeItem(key); return; } return appBridge.safeCall(() => appBridge.removeStorage(key)); }, [isNativeEnvironment]); const logout = useCallback(async (): Promise => { if (!isNativeEnvironment) { throw new Error('Logout is only available in native environment'); } return appBridge.safeCall(() => appBridge.logout()); }, [isNativeEnvironment]); const requestToken = useCallback(async (): Promise => { if (!isNativeEnvironment) { throw new Error('Token request is only available in native environment'); } return appBridge.safeCall(() => appBridge.requestToken()); }, [isNativeEnvironment]); const requestRefreshToken = useCallback(async (): Promise => { if (!isNativeEnvironment) { throw new Error('Token refresh request is only available in native environment'); } return appBridge.safeCall(() => appBridge.requestRefreshToken()); }, [isNativeEnvironment]); const registerBiometric = useCallback(async (): Promise => { if (!isNativeEnvironment) { throw new Error('Biometric auth is only available in native environment'); } return appBridge.safeCall(() => appBridge.registerBiometric()); }, [isNativeEnvironment]); const openBiometricRegistrationPopup = useCallback(async (): Promise => { if (!isNativeEnvironment) { return false; } const result = await appBridge.safeCall(() => appBridge.openBiometricRegistrationPopup(), false); return result || false; }, [isNativeEnvironment]); const closeBiometricRegistrationPopup = useCallback(async (): Promise => { if (!isNativeEnvironment) { return; } return appBridge.safeCall(() => appBridge.closeBiometricRegistrationPopup()); }, [isNativeEnvironment]); const shareContent = useCallback(async (content: ShareContent): Promise => { if (!isNativeEnvironment) { // 웹 환경에서는 Web Share API 사용 (지원되는 경우) if (navigator.share) { try { await navigator.share({ title: content.title, text: content.text, ...(content.url && { url: content.url }) }); return; } catch (error) { console.warn('Web Share API failed:', error); } } // 폴백: 클립보드에 복사 const shareText = `${content.title}\n${content.text}${content.url ? `\n${content.url}` : ''}`; if (navigator.clipboard) { await navigator.clipboard.writeText(shareText); alert('클립보드에 복사되었습니다.'); } else { throw new Error('Sharing is not supported'); } return; } return appBridge.safeCall(() => appBridge.shareContent(content)); }, [isNativeEnvironment]); const isPushNotificationEnabled = useCallback(async (): Promise => { if (!isNativeEnvironment) { return true; } const result = await appBridge.safeCall(() => appBridge.isPushNotificationEnabled(), false); return result || false; }, [isNativeEnvironment]); const openAppSettings = useCallback(async (): Promise => { if (!isNativeEnvironment) { return; } return appBridge.safeCall(() => appBridge.openAppSettings()); }, [isNativeEnvironment]); return { isNativeEnvironment, isAndroid, isIOS, deviceInfo, navigateBack, navigateTo, navigateToLogin, closeWebView, showToast, showAlert, showConfirm, setStorage, removeStorage, shareContent, logout, requestToken, requestRefreshToken, registerBiometric, openBiometricRegistrationPopup, closeBiometricRegistrationPopup, isPushNotificationEnabled, openAppSettings }; };