Add biometric authentication registration functionality

- Implement biometric registration methods in appBridge
- Add openBiometricRegistrationPopup and closeBiometricRegistrationPopup functions
- Integrate biometric registration UI in home page and auth register component
- Fix TypeScript errors in useAppBridge hook

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Jay Sheen
2025-09-15 14:09:28 +09:00
parent 9b8378ccad
commit e00dc65d7b
5 changed files with 67 additions and 8 deletions

View File

@@ -1,19 +1,21 @@
import { IMAGE_ROOT } from '@/shared/constants/common'; import { IMAGE_ROOT } from '@/shared/constants/common';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { AuthRegisterProps } from '../model/types'; import { AuthRegisterProps } from '../model/types';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { useAppBridge } from '@/hooks/useAppBridge';
export const AuthRegister = ({ export const AuthRegister = ({
setAuthRegisterOn, setAuthRegisterOn,
authRegisterOn, authRegisterOn,
}: AuthRegisterProps) => { }: AuthRegisterProps) => {
const { navigate } = useNavigate(); const { registerBiometric, closeBiometricRegistrationPopup } = useAppBridge();
const onClickToClose = () => { const onClickToClose = () => {
closeBiometricRegistrationPopup();
setAuthRegisterOn(false); setAuthRegisterOn(false);
}; };
const onClickToRegister = () => { const onClickToRegister = () => {
// register registerBiometric();
setAuthRegisterOn(false);
}; };
const variants = { const variants = {

View File

@@ -1,6 +1,6 @@
import { useState, useEffect, useCallback } from 'react'; import { useState, useEffect, useCallback } from 'react';
import { appBridge } from '@/utils/appBridge'; import { appBridge } from '@/utils/appBridge';
import { DeviceInfo, LocationInfo, ContactInfo, ShareContent } from '@/types'; import { DeviceInfo, ShareContent } from '@/types';
interface UseAppBridgeReturn { interface UseAppBridgeReturn {
isNativeEnvironment: boolean; isNativeEnvironment: boolean;
@@ -37,6 +37,14 @@ interface UseAppBridgeReturn {
*/ */
// 공유 // 공유
shareContent: (content: ShareContent) => Promise<void>; shareContent: (content: ShareContent) => Promise<void>;
// 간편 인증 등록
registerBiometric: () => Promise<void>;
// 간편 인증 등록 팝업 열기
openBiometricRegistrationPopup: () => Promise<boolean>;
// 간편 인증 등록 팝업 닫기
closeBiometricRegistrationPopup: () => Promise<void>;
} }
export const useAppBridge = (): UseAppBridgeReturn => { export const useAppBridge = (): UseAppBridgeReturn => {
@@ -149,6 +157,28 @@ export const useAppBridge = (): UseAppBridgeReturn => {
return appBridge.safeCall(() => appBridge.removeStorage(key)); return appBridge.safeCall(() => appBridge.removeStorage(key));
}, [isNativeEnvironment]); }, [isNativeEnvironment]);
const registerBiometric = useCallback(async (): Promise<void> => {
if (!isNativeEnvironment) {
throw new Error('Biometric auth is only available in native environment');
}
return appBridge.safeCall(() => appBridge.registerBiometric());
}, [isNativeEnvironment]);
const openBiometricRegistrationPopup = useCallback(async (): Promise<boolean> => {
if (!isNativeEnvironment) {
return false;
}
const result = await appBridge.safeCall(() => appBridge.openBiometricRegistrationPopup(), false);
return result || false;
}, [isNativeEnvironment]);
const closeBiometricRegistrationPopup = useCallback(async (): Promise<void> => {
if (!isNativeEnvironment) {
return;
}
return appBridge.safeCall(() => appBridge.closeBiometricRegistrationPopup());
}, [isNativeEnvironment]);
/* /*
const openCamera = useCallback(async ( const openCamera = useCallback(async (
options?: { quality?: number; allowEdit?: boolean } options?: { quality?: number; allowEdit?: boolean }
@@ -265,6 +295,9 @@ export const useAppBridge = (): UseAppBridgeReturn => {
getLocation, getLocation,
getContacts, getContacts,
*/ */
shareContent shareContent,
registerBiometric,
openBiometricRegistrationPopup,
closeBiometricRegistrationPopup
}; };
}; };

View File

@@ -9,6 +9,7 @@ import { FooterItemActiveKey } from '@/entities/common/model/types';
import { useStore } from '@/shared/model/store'; import { useStore } from '@/shared/model/store';
import { StorageKeys } from '@/shared/constants/local-storage'; import { StorageKeys } from '@/shared/constants/local-storage';
import { setLocalStorage, getLocalStorage } from '@/shared/lib/web-view-bridge'; import { setLocalStorage, getLocalStorage } from '@/shared/lib/web-view-bridge';
import { useAppBridge } from '@/hooks/useAppBridge';
import { HeaderType } from '@/entities/common/model/types'; import { HeaderType } from '@/entities/common/model/types';
import { import {
@@ -20,7 +21,7 @@ import {
export const HomePage = () => { export const HomePage = () => {
const { callLogin } = useUserInfo(); const { callLogin } = useUserInfo();
const { openBiometricRegistrationPopup } = useAppBridge();
useSetHeaderTitle(''); useSetHeaderTitle('');
useSetHeaderType(HeaderType.Home); useSetHeaderType(HeaderType.Home);
useSetFooterMode(true); useSetFooterMode(true);
@@ -85,7 +86,11 @@ export const HomePage = () => {
setBottomBannerOn(sw); setBottomBannerOn(sw);
}; };
const checkAuthRegisterOpen = () => { const checkAuthRegisterOpen = () => {
setAuthRegisterOn(true); openBiometricRegistrationPopup().then((isOpen) => {
if(isOpen){
setAuthRegisterOn(true);
}
});
}; };
@@ -105,7 +110,6 @@ export const HomePage = () => {
}, 500) }, 500)
} }
} }
}; };
/*useLoginMutation /*useLoginMutation

View File

@@ -51,6 +51,10 @@ export enum BridgeMessageType {
// 인증 // 인증
LOGIN = 'login', LOGIN = 'login',
LOGOUT = 'logout', LOGOUT = 'logout',
REGISTER_BIOMETRIC = 'registerBiometric',
OPEN_BIOMETRIC_REGISTRATION_POPUP = 'openBiometricRegistrationPopup',
CLOSE_BIOMETRIC_REGISTRATION_POPUP = 'closeBiometricRegistrationPopup',
// 언어 설정 // 언어 설정
SET_LANGUAGE = 'setLanguage', SET_LANGUAGE = 'setLanguage',

View File

@@ -163,10 +163,26 @@ class AppBridge {
return this.sendMessage(BridgeMessageType.LOGIN, credentials); return this.sendMessage(BridgeMessageType.LOGIN, credentials);
} }
// 로그아웃 요청
async logout(): Promise<void> { async logout(): Promise<void> {
return this.sendMessage(BridgeMessageType.LOGOUT); return this.sendMessage(BridgeMessageType.LOGOUT);
} }
// 간편 인증 등록 요청
async registerBiometric(): Promise<void> {
return this.sendMessage(BridgeMessageType.REGISTER_BIOMETRIC);
}
// 간편 인증 등록 팝업 열기
async openBiometricRegistrationPopup(): Promise<boolean> {
return this.sendMessage(BridgeMessageType.OPEN_BIOMETRIC_REGISTRATION_POPUP);
}
// 간편 인증 등록 팝업 닫기
async closeBiometricRegistrationPopup(): Promise<void> {
return this.sendMessage(BridgeMessageType.CLOSE_BIOMETRIC_REGISTRATION_POPUP);
}
// 언어 설정 // 언어 설정
async setLanguage(language: string): Promise<void> { async setLanguage(language: string): Promise<void> {
return this.sendMessage(BridgeMessageType.SET_LANGUAGE, { language }); return this.sendMessage(BridgeMessageType.SET_LANGUAGE, { language });