Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion Time-Up/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ import SetScheduleRepeatPage from './src/pages/SetScheduleRepeatPage';
import ViewScheduleDetailPage from './src/pages/ViewScheduleDetailPage';

import { getAccessToken } from './src/utils/storage';
import { requestWebPushToken } from './src/utils/webPush';
import { initWebPush } from './src/utils/webPush';
import { requestWebPushToken } from './src/utils/webToken';

const queryClient = new QueryClient();

Expand Down Expand Up @@ -144,6 +145,18 @@ export default function App() {
};
}, []);

useEffect(() => {
(async () => {
try {
const token = await initWebPush();
console.log('FCM 웹 토큰:', token);
// 이미 토큰 저장 API는 구현했다 했으니 여기선 로깅만
} catch (e) {
console.warn('웹 푸시 초기화 실패:', e);
}
})();
}, []);

if (!mapsLoaded || !initialRoute) return null;
const content = (
<GestureHandlerRootView style={{ flex: 1 }}>
Expand Down
2 changes: 1 addition & 1 deletion Time-Up/src/pages/Alarm/My/EditMyAlarmPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
} catch (error: any) {
const status = error?.response?.status;
const apiErr = error?.response?.data?.error;
const apiMsg = error?.response?.data?.message;

Check warning on line 93 in Time-Up/src/pages/Alarm/My/EditMyAlarmPage.tsx

View workflow job for this annotation

GitHub Actions / Lint & Type Check

'apiMsg' is assigned a value but never used

if ((status === 422 || status === 400) &&
(apiErr === 'BusinessLogicError')) {
Expand All @@ -115,7 +115,7 @@
} catch (error) {
console.error(`알람 ${selectedAlarmId} 상태 토글 실패:`, error);
}
}, [selectedAlarmId, isActive]);

Check warning on line 118 in Time-Up/src/pages/Alarm/My/EditMyAlarmPage.tsx

View workflow job for this annotation

GitHub Actions / Lint & Type Check

React Hook useCallback has missing dependencies: 'toggleMyAlarmActivation' and 'updateAlarmField'. Either include them or remove the dependency array

const handleSelectSound = () => {
navigation.navigate('SelectMyAlarmSoundPage');
Expand Down Expand Up @@ -466,7 +466,7 @@
</View>
</View>

<View className="flex-row items-center justify-center gap-10 -mt-[1%]">
<View className="flex-row items-center justify-center gap-10 mt-[4%]">
<AlarmButton title="취소" onPress={handleCancel} backgroundColor="#1C1F21" textColor="#CFD3D7" style={{ width: 120, height: 48 }} />
<AlarmButton title="저장" onPress={handleSave} backgroundColor="#CCCCFF" textColor="black" style={{ width: 120, height: 48 }} />
</View>
Expand Down
2 changes: 1 addition & 1 deletion Time-Up/src/pages/Alarm/My/MyAlarmDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export default function MyAlarmDetailPage() {
</View>
</View>

<View className="flex-row items-center justify-center gap-10 -mt-[1%]">
<View className="flex-row items-center justify-center gap-10 mt-[4%]">
<AlarmButton title="삭제" onPress={handleDelete} backgroundColor="#1C1F21" textColor="#CFD3D7" style={{ width: 120, height: 48 }} />
<AlarmButton title="편집" onPress={handleEdit} backgroundColor="#CCCCFF" textColor="black" style={{ width: 120, height: 48 }} />
</View>
Expand Down
1 change: 0 additions & 1 deletion Time-Up/src/pages/Alarm/My/MyAlarmPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ export default function MyAlarmPage() {
}
};


// const handleToggleAutoAlarm = async () => {
// try {
// if (nextAutoAlarm?.auto_alarm_id != null) {
Expand Down
7 changes: 3 additions & 4 deletions Time-Up/src/pages/Alarm/WakeUp/EditWakeUpAlarmPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { AlarmItem } from '@/src/types/alarm';
import { toPutWakeupAlarmRequest } from '@/src/utils/alarmTransform';
import { BottomSheetModal, BottomSheetView } from '@gorhom/bottom-sheet';
import React, { useCallback, useMemo, useRef, useState } from 'react';
import { Dimensions, Platform, ScrollView, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { Dimensions, Platform, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import ToggleSwitch from '../../../components/common/ToggleSwitch';
import { Day, useAlarmContext } from '../../../contexts/AlarmContext';
Expand Down Expand Up @@ -159,7 +159,6 @@ export default function EditWakeUpAlarmPage() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<BottomLayout>
<ScrollView>
<BottomSheetModal
ref={bottomSheetModalRef}
snapPoints={snapPoints}
Expand Down Expand Up @@ -234,7 +233,7 @@ export default function EditWakeUpAlarmPage() {
</View>

<View className="w-full h-[55%] items-center gap-3 space-y-3">
<View className="w-[91%] h-[80px] bg-dark border border-dark-stroke rounded-3xl items-start justify-start pt-2 pl-3">
<View className="w-[91%] h-[90px] bg-dark border border-dark-stroke rounded-3xl items-start justify-start pt-2 pl-3">
<View className="flex-row items-center">
<IconCalendar width={20} height={20} />
<Text className="font-pretendard text-gray-200 text-xl ml-2">반복요일</Text>
Expand Down Expand Up @@ -356,12 +355,12 @@ export default function EditWakeUpAlarmPage() {
</View>
</View>

</ScrollView>

<View className="flex-row items-center justify-center gap-10 -mt-[4%]">
<AlarmButton title="취소" onPress={handleCancel} backgroundColor="#1C1F21" textColor="#CFD3D7" style={{ width: 120, height: 48 }} />
<AlarmButton title="저장" onPress={handleSave} backgroundColor="#CCCCFF" textColor="black" style={{ width: 120, height: 48 }} />
</View>

</BottomLayout>
</GestureHandlerRootView>
);
Expand Down
2 changes: 1 addition & 1 deletion Time-Up/src/pages/Alarm/WakeUp/WakeUpAlarmDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export default function WakeUpAlarmDetailPage() {
</View>
</View>

<View className="flex-row items-center justify-center -mt-[6%]">
<View className="flex-row items-center justify-center mt-[2%]">
<AlarmButton title="편집" onPress={handleEdit} backgroundColor="#CCCCFF" textColor="black" style={{ width: 120, height: 48 }} />
</View>
</ScrollView>
Expand Down
1 change: 0 additions & 1 deletion Time-Up/src/pages/Onboarding/OnboardingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ export default function OnboardingPage() {
}

if (data.success?.isNew) {
debugger;
try {
await refreshAlarms();
} catch (e) {
Expand Down
69 changes: 21 additions & 48 deletions Time-Up/src/utils/webPush.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// src/utils/webPush.ts
// webPush.ts (예: 앱 시작 시 1회 호출)
import { initializeApp } from 'firebase/app';
import { getMessaging, getToken } from 'firebase/messaging';
import { getMessaging, getToken, isSupported, onMessage } from 'firebase/messaging';

const firebaseConfig = {
apiKey: "AIzaSyAEAKbupll7pRrAuhCtI0SbHRAx-rXj7oM",
Expand All @@ -11,59 +12,31 @@ const firebaseConfig = {
};

const app = initializeApp(firebaseConfig);
export const messaging = getMessaging(app);

// 1) 푸시 권한 요청 + 2) 서비스워커 등록 + 3) FCM 웹 토큰 발급
// export async function requestWebPushToken(): Promise<string | null> {
// if (!('Notification' in window)) return null;

// const permission = await Notification.requestPermission();
// if (permission !== 'granted') return null;

// // 이미 public/index.html에서 /firebase-messaging-sw.js 를 등록했지만,
// // 안전하게 등록 객체를 getToken에 넘겨 위치를 명시. (Firebase 공식 지원)
// const registration = await navigator.serviceWorker.getRegistration('/')
// ?? await navigator.serviceWorker.register('/firebase-messaging-sw.js');

// const token = await getToken(messaging, {
// vapidKey: 'BK6LHOnQzm8od0iib8gPwgv7K6eI43xNDDhpVRLkNTXWZ4jVfxCfaTwy-HPNqHeoiPyM3C3o7sUhPIOHBSetyUc',
// serviceWorkerRegistration: registration,
// });

// return token || null;
// }
export async function initWebPush() {
const supported = await isSupported();
if (!supported) {
console.warn('이 브라우저는 FCM을 지원하지 않습니다.');
return null;
}

export async function requestWebPushToken(): Promise<string | null> {
if (!('Notification' in window)) return null;
const registration = await navigator.serviceWorker.register('/firebase-messaging-sw.js', { scope: '/' });

const permission = await Notification.requestPermission();
if (permission !== 'granted') {
console.warn('웹 푸시 권한 거부됨');
const perm = await Notification.requestPermission();
if (perm !== 'granted') {
console.warn('알림 권한이 거부되었습니다.');
return null;
}

let registration = await navigator.serviceWorker.getRegistration('/');
if (!registration) {
registration = await navigator.serviceWorker.register('/firebase-messaging-sw.js', { scope: '/' });
}
const messaging = getMessaging(app);
const token = await getToken(messaging, {
vapidKey: 'BK6LHOnQzm8od0iib8gPwgv7K6eI43xNDDhpVRLkNTXWZ4jVfxCfaTwy-HPNqHeoiPyM3C3o7sUhPIOHBSetyUc',
serviceWorkerRegistration: registration,
});

// 2) 활성화(ready)까지 대기
await navigator.serviceWorker.ready;
onMessage(messaging, (payload) => {
console.log('[foreground] FCM payload:', payload);
});

try {
const token = await getToken(messaging, {
vapidKey: 'BK6LHOnQzm8od0iib8gPwgv7K6eI43xNDDhpVRLkNTXWZ4jVfxCfaTwy-HPNqHeoiPyM3C3o7sUhPIOHBSetyUc',
serviceWorkerRegistration: registration,
});
if (!token) {
console.warn('토큰이 비어 있음 (권한/HTTPS/도메인/스코프 확인 필요)');
return null;
}
console.log('Web FCM Token:', token); // 정상 발급
return token;
} catch (e: any) {
console.error('getToken 실패:', e?.code, e?.message, e);
return null;
}
return token;
}

69 changes: 69 additions & 0 deletions Time-Up/src/utils/webToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// src/utils/webToken.ts
import { initializeApp } from 'firebase/app';
import { getMessaging, getToken } from 'firebase/messaging';

const firebaseConfig = {
apiKey: "AIzaSyAEAKbupll7pRrAuhCtI0SbHRAx-rXj7oM",
authDomain: "timeup-80358.firebaseapp.com",
projectId: "timeup-80358",
messagingSenderId: "482152461783",
appId: "1:482152461783:web:8ee854bcf8cad1ab3bc792",
};

const app = initializeApp(firebaseConfig);
export const messaging = getMessaging(app);

// 1) 푸시 권한 요청 + 2) 서비스워커 등록 + 3) FCM 웹 토큰 발급
// export async function requestWebPushToken(): Promise<string | null> {
// if (!('Notification' in window)) return null;

// const permission = await Notification.requestPermission();
// if (permission !== 'granted') return null;

// // 이미 public/index.html에서 /firebase-messaging-sw.js 를 등록했지만,
// // 안전하게 등록 객체를 getToken에 넘겨 위치를 명시. (Firebase 공식 지원)
// const registration = await navigator.serviceWorker.getRegistration('/')
// ?? await navigator.serviceWorker.register('/firebase-messaging-sw.js');

// const token = await getToken(messaging, {
// vapidKey: 'BK6LHOnQzm8od0iib8gPwgv7K6eI43xNDDhpVRLkNTXWZ4jVfxCfaTwy-HPNqHeoiPyM3C3o7sUhPIOHBSetyUc',
// serviceWorkerRegistration: registration,
// });

// return token || null;
// }

export async function requestWebPushToken(): Promise<string | null> {
if (!('Notification' in window)) return null;

const permission = await Notification.requestPermission();
if (permission !== 'granted') {
console.warn('웹 푸시 권한 거부됨');
return null;
}

let registration = await navigator.serviceWorker.getRegistration('/');
if (!registration) {
registration = await navigator.serviceWorker.register('/firebase-messaging-sw.js', { scope: '/' });
}

// 2) 활성화(ready)까지 대기
await navigator.serviceWorker.ready;

try {
const token = await getToken(messaging, {
vapidKey: 'BK6LHOnQzm8od0iib8gPwgv7K6eI43xNDDhpVRLkNTXWZ4jVfxCfaTwy-HPNqHeoiPyM3C3o7sUhPIOHBSetyUc',
serviceWorkerRegistration: registration,
});
if (!token) {
console.warn('토큰이 비어 있음 (권한/HTTPS/도메인/스코프 확인 필요)');
return null;
}
console.log('Web FCM Token:', token); // 정상 발급
return token;
} catch (e: any) {
console.error('getToken 실패:', e?.code, e?.message, e);
return null;
}
}

Loading