diff --git a/src/components/PoseDetector.tsx b/src/components/PoseDetector.tsx index 342b41f..944aba4 100644 --- a/src/components/PoseDetector.tsx +++ b/src/components/PoseDetector.tsx @@ -29,7 +29,7 @@ const PoseDetector: React.FC = () => { const [isModelLoaded, setIsModelLoaded] = useState(false) // const [isSnapShotSaved, setIsSnapSaved] = useState(false) - const { showNotification } = usePushNotification() + const { showNotification, hasPermission: hasNotiPermisson } = usePushNotification() const { isPopupOpen, handleClosePopup, openPopup } = useGuidePopup() @@ -46,7 +46,7 @@ const PoseDetector: React.FC = () => { const shoulderTwistCnt = useRef(0) const chinUtpCnt = useRef(0) const tailboneSitCnt = useRef(0) - + const isShowImmediNotiRef = useRef(false) const canvasRef = useRef(null) const { isSnapShotSaved, snapshot, setSnapShot } = useSnapShotStore() @@ -56,7 +56,6 @@ const PoseDetector: React.FC = () => { // const userNoti = useNotificationStore((state) => state.notification) const { notification } = useNotification() - const { requestNotificationPermission } = usePushNotification() const { hasPermission } = useCameraPermission() const location = useLocation() // 페이지 이동 감지 @@ -119,8 +118,7 @@ const PoseDetector: React.FC = () => { timerRef: React.MutableRefObject, poseType: poseType, isSnapShotSaved: boolean, - cntRef: React.MutableRefObject, - isShowNoti: boolean | undefined + cntRef: React.MutableRefObject ): void => { if (condition && isSnapShotSaved) { if (!timerRef.current) { @@ -130,7 +128,7 @@ const PoseDetector: React.FC = () => { const req = { snapshot: { keypoints, score }, type: poseType } sendPoseMutation.mutate(req) cntRef.current = cntRef.current + 1 - if (isShowNoti) + if (isShowImmediNotiRef.current) showNotification(`척추 건강 위험! ${getPoseName(poseType)} 감지! 자세를 바르게 앉아주세요.`) } }, 30 * 1000) @@ -151,7 +149,6 @@ const PoseDetector: React.FC = () => { const _isTextNeck = detectTextNeck(snapRef.current, results, true, 0.88) const _isHandOnChin = detectHandOnChin(snapRef.current, results) const _isTailboneSit = detectTailboneSit(snapRef.current, results) - const _isShowNoti = notification?.duration === "IMMEDIATELY" && notification?.isActive if (_isShoulderTwist !== null) setIsShoulderTwist(_isShoulderTwist) if (_isTextNeck !== null) setIsTextNeck(_isTextNeck) @@ -159,17 +156,10 @@ const PoseDetector: React.FC = () => { if (_isTailboneSit !== null) setIsTailboneSit(_isTailboneSit) // 공통 타이머 관리 함수 호출 - managePoseTimer(_isTextNeck, turtleNeckTimer, "TURTLE_NECK", isSnapShotSaved, turtleNeckCnt, _isShowNoti) - managePoseTimer( - _isShoulderTwist, - shoulderTwistTimer, - "SHOULDER_TWIST", - isSnapShotSaved, - shoulderTwistCnt, - _isShowNoti - ) - managePoseTimer(_isTailboneSit, tailboneSitTimer, "TAILBONE_SIT", isSnapShotSaved, tailboneSitCnt, _isShowNoti) - managePoseTimer(_isHandOnChin, chinUtpTimer, "CHIN_UTP", isSnapShotSaved, chinUtpCnt, _isShowNoti) + managePoseTimer(_isTextNeck, turtleNeckTimer, "TURTLE_NECK", isSnapShotSaved, turtleNeckCnt) + managePoseTimer(_isShoulderTwist, shoulderTwistTimer, "SHOULDER_TWIST", isSnapShotSaved, shoulderTwistCnt) + managePoseTimer(_isTailboneSit, tailboneSitTimer, "TAILBONE_SIT", isSnapShotSaved, tailboneSitCnt) + managePoseTimer(_isHandOnChin, chinUtpTimer, "CHIN_UTP", isSnapShotSaved, chinUtpCnt) const isRight = !_isTextNeck && !_isHandOnChin && !_isShoulderTwist && !_isTailboneSit if (canvasRef.current) drawPose(results, canvasRef.current, isRight) } else { @@ -288,7 +278,6 @@ const PoseDetector: React.FC = () => { }, [location]) useEffect(() => { - requestNotificationPermission() getScript() }, []) @@ -328,6 +317,12 @@ const PoseDetector: React.FC = () => { } }, [notification, isSnapShotSaved]) + // 즉시 알림을 사용 하는 경우, 푸시를 보낼지 여부를 저장 + useEffect(() => { + isShowImmediNotiRef.current = + notification?.duration === "IMMEDIATELY" && (notification?.isActive as boolean) && hasNotiPermisson + }, [notification?.duration, notification?.isActive, hasNotiPermisson]) + // 팝업 열기 const handleShowPopup = (): void => { openPopup() diff --git a/src/hooks/usePushNotification.ts b/src/hooks/usePushNotification.ts index b1481c9..c83a4f9 100644 --- a/src/hooks/usePushNotification.ts +++ b/src/hooks/usePushNotification.ts @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react" +import { useState, useEffect, useRef } from "react" interface UsePushNotificationResult { hasPermission: boolean @@ -12,6 +12,14 @@ const usePushNotification = (): UsePushNotificationResult => { const [hasPermission, setHasPermission] = useState(false) // 권한이 허용되었는지 여부 const [isPermissionDenied, setIsPermissionDenied] = useState(false) // 권한이 거부되었는지 여부 + // 최신 상태 추적용 useRef + const hasPermissionRef = useRef(hasPermission) + + useEffect(() => { + // 최신 hasPermission 값을 항상 유지 + hasPermissionRef.current = hasPermission + }, [hasPermission]) + // 권한 변경을 처리하는 함수 const handlePermissionChange = (permission: NotificationPermission): void => { if (permission === "granted") { @@ -42,7 +50,7 @@ const usePushNotification = (): UsePushNotificationResult => { // 알림 표시 함수 const showNotification = (body: string): void => { - if (hasPermission) { + if (hasPermissionRef.current) { new Notification("자세공작소", { body: body, })