Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PWA 이용을 위한 manifest.json 작성 #403

Merged
merged 9 commits into from
Aug 20, 2024
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 51 additions & 0 deletions frontend/public/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"description": "",
"background_color": "#ffffff",
"dir": "ltr",
"display": "standalone",
"name": "dev.mouda",
"orientation": "portrait",
"scope": "/",
"short_name": "dev.mouda",
"start_url": "/",
"theme_color": "#ffffff",
"icons": [
{
"src": "./android/android-launchericon-512-512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "./android/android-launchericon-192-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "./android/android-launchericon-144-144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "./android/android-launchericon-96-96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "./android-launchericon-72-72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "./android-launchericon-48-48.png",
"sizes": "48x48",
"type": "image/png"
}
],
"lang": "ko",
"display_override": [
"window-controls-overlay"
],
"categories": [
"social"
]
}
2 changes: 1 addition & 1 deletion frontend/src/apis/posts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export const postPlease = async (please: PleaseInfoInput) => {
};

export const postNotificationToken = async (currentToken: string) => {
await ApiClient.postWithLastDarakbangId('notification/register', {
await ApiClient.postWithAuth('notification/register', {
token: currentToken,
});
};
Expand Down
4 changes: 0 additions & 4 deletions frontend/src/components/LoginForm/LoginForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ import { useNavigate } from 'react-router-dom';
import ROUTES from '@_constants/routes';
import { setToken } from '@_utils/tokenManager';
import { login } from '@_apis/auth';
import { requestPermission } from '@_service/notification';
import useServeToken from '@_hooks/mutaions/useServeToken';

// TODO: 로그인 기능 요구사항 변경 예정
export default function LoginForm() {
const navigate = useNavigate();
const { mutate } = useServeToken();

const [nickname, setNickname] = useState('');
const [isValid, setIsValid] = useState(false);
Expand All @@ -26,7 +23,6 @@ export default function LoginForm() {

const response = await login({ nickname });
setToken(response.data.accessToken);
requestPermission(mutate);
navigate(ROUTES.main);
};

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>모우다</title>
<link rel="manifest" href="/manifest.json" /> <title>모우다</title>
</head>
<body>
<div id="root"></div>
Expand Down
13 changes: 1 addition & 12 deletions frontend/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,6 @@ if (process.env.REACT_APP_GOOGLE_ANALYTICS) {
ReactGA.initialize(process.env.REACT_APP_GOOGLE_ANALYTICS);
}

if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register(`/firebase-messaging-sw.js`)
.then((registration) => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch((error) => {
console.log('Service Worker registration failed:', error);
});
}

Sentry.init({
dsn: process.env.SENTRY_DSN,
integrations: [
Expand All @@ -30,7 +19,7 @@ Sentry.init({
// Performance Monitoring
tracesSampleRate: 1.0, // Capture 100% of the transactions
// Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
tracePropagationTargets: ['http://43.202.67.25/'],
tracePropagationTargets: ['https://dev.mouda.site/'],
// Session Replay
replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/pages/MainPage/MainPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ import SolidArrow from '@_components/Icons/SolidArrow';
import useMyDarakbangs from '@_hooks/queries/useMyDarakbang';
import useMyRoleInDarakbang from '@_hooks/queries/useMyDarakbangRole';
import { useNavigate } from 'react-router-dom';

import { requestPermission } from '@_service/notification';
import useServeToken from '@_hooks/mutaions/useServeToken';
export default function MainPage() {
const navigate = useNavigate();

const { mutate } = useServeToken();
const [currentTab, setCurrentTab] = useState<MainPageTab>('모임목록');
const [isDarakbangMenuOpened, setIsDarakbangMenuOpened] = useState(false);

Expand All @@ -40,6 +41,7 @@ export default function MainPage() {

const handleNotification = () => {
navigate(ROUTES.notification);
requestPermission(mutate);
};

const darakbangMenuOption = useMemo(() => {
Expand Down
66 changes: 42 additions & 24 deletions frontend/src/service/forgroundMessage.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,50 @@
import { getMessaging, onMessage } from 'firebase/messaging';
import { app } from './initFirebase';

// Firebase Messaging 인스턴스 가져오기
const messaging = getMessaging(app);
function initializeForegroundMessageHandling() {
const messaging = getMessaging(app);

onMessage(messaging, (payload) => {
console.log('포그라운드 알림 도착: ', payload);
onMessage(messaging, (payload) => {
console.log('포그라운드 알림 도착: ', payload);

const notificationTitle = payload.notification?.title;
const notificationOptions = {
body: payload.notification?.body,
icon: payload.notification?.icon, // 알림 아이콘 설정
data: { link: payload.fcmOptions?.link || '/' }, // 알림 클릭 시 이동할 링크 설정
};
const notificationTitle = payload.notification?.title || '알림';
const notificationOptions = {
body: payload.notification?.body || '',
icon: payload.notification?.icon,
data: { link: payload.fcmOptions?.link || '/' },
};

if (Notification.permission === 'granted') {
const notification = new Notification(
notificationTitle!,
notificationOptions,
);
if (Notification.permission === 'granted') {
try {
const notification = new Notification(
notificationTitle,
notificationOptions,
);

notification.onclick = function (event) {
event.preventDefault(); // 기본 동작 방지 (필요한 경우)
notification.onclick = function (event) {
event.preventDefault();
window.open(notificationOptions.data.link, '_blank');
};
} catch (error) {
console.error('알림 생성 중 오류 발생:', error);
}
} else {
console.warn('알림 권한이 허용되지 않았습니다.');
}
});
}

// 알림 클릭 시 페이지 이동
window.open(notificationOptions.data.link, '_blank');
};
} else {
console.warn('알림 권한이 허용되지 않았습니다.');
}
});
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register(`/firebase-messaging-sw.js`)
.then((registration) => {
console.log('Service Worker registered with scope:', registration.scope);
initializeForegroundMessageHandling();
})
.catch((error) => {
console.log('Service Worker registration failed:', error);
});
} else {
// 서비스 워커가 지원되지 않는 경우에도 포그라운드 메시지 처리를 초기화
initializeForegroundMessageHandling();
}
1 change: 1 addition & 0 deletions frontend/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './src/index.html'),
manifest: path.resolve(__dirname, './public/manifest.json'),
}),
new webpack.DefinePlugin({
'process.env': JSON.stringify(process.env),
Expand Down
6 changes: 6 additions & 0 deletions frontend/webpack.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const { sentryWebpackPlugin } = require('@sentry/webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = merge(common, {
mode: 'production',
Expand Down Expand Up @@ -47,5 +48,10 @@ module.exports = merge(common, {
org: '2024-mouda',
project: 'javascript-react',
}),
new CopyWebpackPlugin({
patterns: [
{ from: 'public', to: '' }, // public 폴더의 모든 파일을 dist 폴더의 루트로 복사
],
}),
],
});
Loading