-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'upstream/fcm-click'
- Loading branch information
Showing
8 changed files
with
441 additions
and
199 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { useMutation } from "@tanstack/react-query"; | ||
import { apiClient } from "../instance"; | ||
|
||
interface FcmOffsetUpdateRequest { | ||
token: string; | ||
notificationOffset: number; | ||
} | ||
|
||
type FcmOffsetUpdateResponse = string; | ||
|
||
const useFcmOffsetUpdate = () => { | ||
return useMutation<FcmOffsetUpdateResponse, Error, FcmOffsetUpdateRequest>({ | ||
mutationFn: async (data: FcmOffsetUpdateRequest) => { | ||
// query parameter로 변경 | ||
const response = await apiClient.put<FcmOffsetUpdateResponse>( | ||
"/api/fcm/update/notification-offset", | ||
null, // body는 null로 설정 | ||
{ | ||
params: { | ||
// query parameters로 전송 | ||
token: data.token, | ||
notificationOffset: data.notificationOffset, | ||
}, | ||
}, | ||
); | ||
return response.data; | ||
}, | ||
onError: (error) => { | ||
console.error("FCM 알림 오프셋 업데이트 실패:", error); | ||
}, | ||
}); | ||
}; | ||
|
||
export default useFcmOffsetUpdate; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,35 @@ | ||
import { useMutation } from "@tanstack/react-query"; | ||
import { apiClient } from "../instance"; | ||
import { apiClient } from "@/api/instance"; | ||
|
||
interface FcmUpdateRequest { | ||
interface UpdateNotificationEnabledRequest { | ||
token: string; | ||
isNotificatioinEnabled?: boolean; | ||
notificationOffset?: number; | ||
isNotificationEnabled: boolean; | ||
} | ||
|
||
interface FcmUpdateResponse { | ||
message: string; | ||
} | ||
|
||
const useFcmUpdate = () => { | ||
return useMutation<FcmUpdateResponse, Error, FcmUpdateRequest>({ | ||
mutationFn: async (data: FcmUpdateRequest) => { | ||
const response = await apiClient.put<FcmUpdateResponse>( | ||
"/api/fcm/update", | ||
export const useUpdateNotificationEnabled = () => { | ||
return useMutation({ | ||
mutationFn: async ({ | ||
token, | ||
isNotificationEnabled, | ||
}: UpdateNotificationEnabledRequest) => { | ||
const response = await apiClient.put( | ||
`/api/fcm/update/notification-enabled?token=${token}&isNotificationEnabled=${isNotificationEnabled}`, | ||
{}, // 빈 body | ||
{ | ||
token: data.token, | ||
isNotificationEnabled: data.isNotificatioinEnabled ?? true, | ||
notificationOffset: data.notificationOffset ?? 0, | ||
withCredentials: true, | ||
}, | ||
); | ||
|
||
return response.data; | ||
}, | ||
onError: (error) => { | ||
console.error("FCM 토큰 업데이트 실패:", error); | ||
onError: (error: any) => { | ||
if (error.response?.status === 401) { | ||
console.error("인증 정보가 없거나 만료되었습니다."); | ||
} else { | ||
console.error("알림 설정 업데이트 실패:", error); | ||
} | ||
}, | ||
}); | ||
}; | ||
|
||
export default useFcmUpdate; | ||
export default useUpdateNotificationEnabled; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { useEffect, useRef } from "react"; | ||
import { requestForToken, setupOnMessageListener } from "@/api/firebaseConfig"; | ||
import { apiClient } from "@/api/instance"; | ||
|
||
const FCM_TOKEN_KEY = "fcm_token"; | ||
|
||
// 모듈 레벨에서 전역 플래그 선언 | ||
let isTokenRequestedGlobal = false; | ||
|
||
const useNotificationSetup = () => { | ||
const tokenRequestedRef = useRef(false); | ||
|
||
// 브라우저별 알림 설정 안내 메시지 | ||
const openNotificationSettings = () => { | ||
const { userAgent } = navigator; | ||
if (userAgent.includes("Edg")) { | ||
alert( | ||
"Edge 설정에서 알림을 활성화해주세요:\n설정 > 쿠키 및 사이트 권한 > 알림", | ||
); | ||
} else if (userAgent.includes("Chrome")) { | ||
alert( | ||
"Chrome 설정에서 알림을 활성화해주세요:\n설정 > 개인정보 및 보안 > 사이트 설정 > 알림", | ||
); | ||
} else if ( | ||
userAgent.includes("Safari") && | ||
!userAgent.includes("Chrome") && | ||
!userAgent.includes("Edg") | ||
) { | ||
alert( | ||
"Safari 설정에서 알림을 활성화해주세요:\nmacOS에서는 Safari > 설정 > 알림\niOS에서는 설정 > Safari > 알림", | ||
); | ||
} else if (userAgent.includes("Firefox")) { | ||
alert( | ||
"Firefox 설정에서 알림을 활성화해주세요:\n설정 페이지에서 개인정보 및 보안 > 권한 > 알림", | ||
); | ||
} else { | ||
alert("알림을 활성화하려면 브라우저 설정을 확인해주세요."); | ||
} | ||
}; | ||
|
||
useEffect(() => { | ||
const initializeFCM = async () => { | ||
// 알림 API 지원 여부 확인 | ||
if (!("Notification" in window)) { | ||
alert("현재 사용 중인 브라우저는 알림 기능을 지원하지 않습니다."); | ||
return; | ||
} | ||
|
||
// 이미 토큰 요청이 진행 중이거나 완료된 경우 중복 실행 방지 | ||
if (isTokenRequestedGlobal || tokenRequestedRef.current) { | ||
return; | ||
} | ||
|
||
try { | ||
isTokenRequestedGlobal = true; // 전역 플래그 설정 | ||
tokenRequestedRef.current = true; | ||
|
||
const existingToken = localStorage.getItem(FCM_TOKEN_KEY); | ||
if (!existingToken) { | ||
if (Notification.permission === "denied") { | ||
openNotificationSettings(); | ||
return; | ||
} | ||
|
||
const permission = await Notification.requestPermission(); | ||
if (permission === "granted") { | ||
const fcmToken = await requestForToken(); | ||
if (fcmToken) { | ||
await apiClient.post("/api/fcm/register", { token: fcmToken }); | ||
localStorage.setItem(FCM_TOKEN_KEY, fcmToken); | ||
console.log("New FCM token registered and saved:", fcmToken); | ||
} | ||
} else if (permission === "denied") { | ||
alert( | ||
"알림 권한이 거부되었습니다. 브라우저 설정에서 알림을 활성화해주세요.", | ||
); | ||
openNotificationSettings(); | ||
} | ||
} | ||
|
||
// 메시지 리스너 설정 | ||
setupOnMessageListener(); | ||
} catch (error) { | ||
console.error("Failed to initialize FCM:", error); | ||
// 에러 발생 시 플래그 초기화 | ||
isTokenRequestedGlobal = false; | ||
tokenRequestedRef.current = false; | ||
} | ||
}; | ||
|
||
initializeFCM(); | ||
|
||
return () => { | ||
tokenRequestedRef.current = false; | ||
}; | ||
}, []); | ||
|
||
const getFCMToken = () => { | ||
return localStorage.getItem(FCM_TOKEN_KEY); | ||
}; | ||
|
||
return { | ||
getFCMToken, | ||
openNotificationSettings, | ||
}; | ||
}; | ||
|
||
export default useNotificationSetup; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.