[refactor/native/menu-#236] 메뉴 전체 리팩토링 및 알림 설정 권한 요청 변경#237
[refactor/native/menu-#236] 메뉴 전체 리팩토링 및 알림 설정 권한 요청 변경#237
Conversation
…ling and state synchronization in NotificationSettingsScreen
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
b0nsu
left a comment
There was a problem hiding this comment.
리뷰 남깁니다. 동작 회귀 가능성이 있는 지점 위주로 확인했습니다.
- [P1] OS 알림 권한이 꺼져 있을 때, 푸시 OFF도 막히는 문제
- 파일: apps/native/src/features/student/menu/screens/NotificationSettingsScreen.tsx (handlePushEnabledChange)
- 현재 로직은
!osPermissionGranted이면newValue와 무관하게 무조건Linking.openSettings()로 빠집니다. - 그래서 앱 토글이 ON 상태 + OS 권한 OFF 상태일 때, 사용자가 앱 내 푸시를 OFF 하려 해도 불가능합니다.
- 제안:
if (!osPermissionGranted && newValue) { openSettings }처럼 ON 시도일 때만 설정 화면 이동 처리
- [P1] OS 권한 허용 복귀 시 마케팅/서비스/QnA 토글을 강제로 모두 ON 처리
- 파일: apps/native/src/features/student/menu/screens/NotificationSettingsScreen.tsx (syncPermission)
!wasGranted && granted분기에서 4개 토글을 모두true로 저장하고 서버에도 그대로 반영합니다.- 사용자가 기존에 마케팅 알림을 OFF 해둔 상태였다면 의도와 다르게 다시 ON 될 수 있습니다.
- 제안: OS 권한 변화는 마스터 푸시만 동기화하고, 세부 수신 동의값(특히 마케팅)은 기존 사용자 설정을 보존
- [P2] 권한 동기화 실패 시 롤백 값이 잘못 복원되는 문제
- 파일: apps/native/src/features/student/menu/screens/NotificationSettingsScreen.tsx (onError rollback)
- 해당 분기는 조건상 항상
wasGranted === false경로라 현재 구현대로면 롤백 시 4개 토글을 전부false로 내립니다. - 즉 실패 전의 실제 사용자 설정으로 복원되지 않습니다.
- 제안: optimistic 변경 직전 상태(snapshot)를 저장해 실패 시 그 값으로 복원
- [P2] 휴대폰 인증 타이머가 wall-clock 기반이 아니라 백그라운드 복귀 시 드리프트 발생
- 파일: apps/native/src/features/student/menu/screens/info/edit/EditPhoneNumberScreen.tsx
- 기존 endTime 기반 계산에서 단순
setInterval감소로 변경되어, 앱 백그라운드 동안 경과 시간이 반영되지 않습니다. - 결과적으로 실제 만료보다 UI 잔여 시간이 더 길게 보이거나 재전송 가능 시점이 늦어질 수 있습니다.
- 제안:
expiresAt을 저장하고remaining = max(0, floor((expiresAt - Date.now())/1000))방식으로 계산
There was a problem hiding this comment.
Pull request overview
학생 메뉴 영역(내 정보/설정/공지/약관/탈퇴 등) 화면 및 공용 컴포넌트를 전반적으로 리팩토링하고, 푸시 알림 권한/설정 동기화 로직을 개선하려는 PR입니다.
Changes:
- 메뉴/내정보 관련 UI를
AnimatedPressable,contentContainerClassName등으로 정리하고 일부 렌더링/메모이제이션을 개선 - 내 정보 화면에서 연동 계정(provider) 표기 포맷터 추가
- 알림 설정 화면에서 OS 권한 상태와 앱 내 토글 상태를 동기화하도록 로직 확장
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/native/src/features/student/menu/screens/info/edit/EditSchoolScreen.tsx | 학교 검색 드롭다운 UX 및 Pressable 교체/쿼리 enabled 처리 |
| apps/native/src/features/student/menu/screens/info/edit/EditPhoneNumberScreen.tsx | 휴대폰 인증 UI 레이아웃 개편 및 타이머/쿼리 invalidate 추가 |
| apps/native/src/features/student/menu/screens/info/edit/EditNicknameScreen.tsx | 객체 shorthand 정리 |
| apps/native/src/features/student/menu/screens/info/MyInfoScreen.tsx | provider 표시 포맷팅 추가 및 ScrollView 컨테이너 클래스 정리 |
| apps/native/src/features/student/menu/screens/WithdrawalScreen.tsx | 탈퇴 처리 async/await 정리 및 항목 Pressable 교체 |
| apps/native/src/features/student/menu/screens/TermsScreen.tsx | 약관 리스트 항목 Pressable 교체(현재 onPress 로직 비어있음) |
| apps/native/src/features/student/menu/screens/NotificationSettingsScreen.tsx | OS 알림 권한 체크 + 토글 동기화/저장 로직 대폭 변경 |
| apps/native/src/features/student/menu/screens/NoticeScreen.tsx | readNotice 콜백화 및 FlatList 스타일 상수화 |
| apps/native/src/features/student/menu/screens/MenuScreen.tsx | ScrollView contentContainer 및 unreadCount 처리/콜백 전달 정리 |
| apps/native/src/features/student/menu/screens/FeedbackScreen.tsx | 피드백 제출 성공/실패 처리 및 pending 상태로 버튼 disable |
| apps/native/src/features/student/menu/components/UserProfileCard.tsx | 학년 라벨 포맷을 gradeOptions 기반으로 통일하고 useMemo 적용 |
| apps/native/src/features/student/menu/components/SettingsToggleItem.tsx | Switch trackColor 상수화 및 조건 렌더링 단순화 |
| apps/native/src/features/student/menu/components/ScreenLayout.tsx | 뒤로가기 버튼 접근성 속성 추가 |
| apps/native/src/features/student/menu/components/MobileProfileCard.tsx | 학년 라벨 포맷을 gradeOptions 기반으로 통일하고 useMemo 적용 |
| apps/native/src/features/student/menu/components/MenuListItem.tsx | 접근성 라벨 추가 및 조건 렌더링 정리 |
| apps/native/src/features/student/menu/components/InfoSection.tsx | fields map key를 index → label로 변경 |
| apps/native/src/features/student/menu/components/IconMenuItem.tsx | 접근성 라벨 추가 및 불필요 prop 제거 |
| apps/native/src/features/student/menu/components/EditScreenLayout.tsx | ScrollView contentContainer 스타일을 className 기반으로 변경 |
Comments suppressed due to low confidence (1)
apps/native/src/features/student/menu/screens/info/edit/EditSchoolScreen.tsx:42
useGetSchoolis disabled whendebouncedQueryis empty, but React Query will keep the previousdatavalue. This means clearing the input (e.g., viahandleClear) can still show stale dropdown results from the last non-empty query. Consider explicitly clearing/hiding the dropdown when the query becomes empty (or keep the query enabled with an empty string so results reset).
const debouncedQuery = useDebounce(query.trim(), 300);
const { data, isLoading } = useGetSchool(
{ query: debouncedQuery },
debouncedQuery.length > 0
);
const results = data?.data ?? [];
const showDropdown = dropdownVisible && (results.length > 0 || isLoading);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
apps/native/src/features/student/menu/screens/info/edit/EditSchoolScreen.tsx
Outdated
Show resolved
Hide resolved
| useEffect(() => { | ||
| if (!endTime) return; | ||
|
|
||
| const interval = setInterval(() => { | ||
| const remaining = Math.max(0, Math.floor((endTime - Date.now()) / 1000)); | ||
| if (!isCodeSent || expiresAt === null) { | ||
| return; | ||
| } | ||
|
|
||
| const syncRemainingTime = () => { | ||
| const remaining = Math.max(0, Math.floor((expiresAt - Date.now()) / 1000)); | ||
| setTimer(remaining); | ||
|
|
||
| if (remaining === 0) { | ||
| clearInterval(interval); | ||
| // 여기서 인증 만료 처리해도 됨 | ||
| setExpiresAt(null); | ||
| } | ||
| }, 1000); | ||
| }; |
There was a problem hiding this comment.
When the timer reaches 0 you only set expiresAt to null, but isCodeSent remains true, so the verification-code input stays visible even though the code is expired (and the CTA switches back to “인증번호 받기”). Consider also resetting isCodeSent/verificationCode/verifyFeedbackMessage on expiry, or condition the verification UI on expiresAt !== null.
There was a problem hiding this comment.
This has already been addressed in 861ec8b.
On expiry, we now call resetVerificationSession() which clears isCodeSent, verificationCode, verifyFeedbackMessage, expiresAt, and
timer, so the verification UI no longer remains visible after expiration.
apps/native/src/features/student/menu/screens/NotificationSettingsScreen.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
✅ Key Changes
case-1: 메뉴 화면 12개 파일 리팩토링
MyInfoScreen providerFormatter 추가
NotificationSettingsScreen 권한 처리 개선
case-2: 메뉴 컴포넌트 14개 파일 리팩토링