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 { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { AuthRegisterProps } from '../model/types';
import { motion } from 'framer-motion';
import { useAppBridge } from '@/hooks/useAppBridge';
export const AuthRegister = ({
setAuthRegisterOn,
authRegisterOn,
}: AuthRegisterProps) => {
const { navigate } = useNavigate();
const { registerBiometric, closeBiometricRegistrationPopup } = useAppBridge();
const onClickToClose = () => {
closeBiometricRegistrationPopup();
setAuthRegisterOn(false);
};
const onClickToRegister = () => {
// register
registerBiometric();
setAuthRegisterOn(false);
};
const variants = {

View File

@@ -1,6 +1,6 @@
import { useState, useEffect, useCallback } from 'react';
import { appBridge } from '@/utils/appBridge';
import { DeviceInfo, LocationInfo, ContactInfo, ShareContent } from '@/types';
import { DeviceInfo, ShareContent } from '@/types';
interface UseAppBridgeReturn {
isNativeEnvironment: boolean;
@@ -37,6 +37,14 @@ interface UseAppBridgeReturn {
*/
// 공유
shareContent: (content: ShareContent) => Promise<void>;
// 간편 인증 등록
registerBiometric: () => Promise<void>;
// 간편 인증 등록 팝업 열기
openBiometricRegistrationPopup: () => Promise<boolean>;
// 간편 인증 등록 팝업 닫기
closeBiometricRegistrationPopup: () => Promise<void>;
}
export const useAppBridge = (): UseAppBridgeReturn => {
@@ -149,6 +157,28 @@ export const useAppBridge = (): UseAppBridgeReturn => {
return appBridge.safeCall(() => appBridge.removeStorage(key));
}, [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 (
options?: { quality?: number; allowEdit?: boolean }
@@ -265,6 +295,9 @@ export const useAppBridge = (): UseAppBridgeReturn => {
getLocation,
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 { StorageKeys } from '@/shared/constants/local-storage';
import { setLocalStorage, getLocalStorage } from '@/shared/lib/web-view-bridge';
import { useAppBridge } from '@/hooks/useAppBridge';
import { HeaderType } from '@/entities/common/model/types';
import {
@@ -20,7 +21,7 @@ import {
export const HomePage = () => {
const { callLogin } = useUserInfo();
const { openBiometricRegistrationPopup } = useAppBridge();
useSetHeaderTitle('');
useSetHeaderType(HeaderType.Home);
useSetFooterMode(true);
@@ -85,7 +86,11 @@ export const HomePage = () => {
setBottomBannerOn(sw);
};
const checkAuthRegisterOpen = () => {
setAuthRegisterOn(true);
openBiometricRegistrationPopup().then((isOpen) => {
if(isOpen){
setAuthRegisterOn(true);
}
});
};
@@ -105,7 +110,6 @@ export const HomePage = () => {
}, 500)
}
}
};
/*useLoginMutation

View File

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

View File

@@ -163,10 +163,26 @@ class AppBridge {
return this.sendMessage(BridgeMessageType.LOGIN, credentials);
}
// 로그아웃 요청
async logout(): Promise<void> {
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> {
return this.sendMessage(BridgeMessageType.SET_LANGUAGE, { language });