Repository navigation
feat(app): 서버 알림을 수신·이동·알림함·설정까지 잇는다 (#2321) - #2322
Merged
Merged
Conversation
- 설치 UUID 를 만들어 push-tokens 등록에 installationId·notificationPermission 을 싣고,
로그인·포그라운드 복귀 때 push-installations 로 OS 알림 권한을 보고한다.
- data-only v1 payload(schemaVersion·destination·notificationId)를 읽어 알림을 그리고,
서버 알림 ID 를 발생 식별자와 탭 Intent 에 싣는다.
- 탭하면 notifications/{id}/target 으로 현재 목적지를 확인하고 읽음 처리한다. 지워진 대상은
목록과 안내를 띄우고, 조회 실패·시간 초과면 payload 목적지로 연다.
- 서버 B 알림과 겹치는 로컬 09:00 데일리 알림을 제거하고 남은 예약·채널을 지운다.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sadturtleman
enabled auto-merge
October 27, 2026 07:33
Sadturtleman
disabled auto-merge
October 27, 2026 07:39
- 탭한 알림의 서버 data(destination·ID·action)를 끝까지 실어 마음의 기록 상세·오늘 질문, 타임레터 상세·수정·수신인 지정 작성, 설정의 수신인·대리인 화면까지 연다. /target 조회가 실패하면 실어 온 data 로, 그것도 없으면 탭으로 연다. - 로그인마다 앱 진입을 보고하고 쉬운 질문 시트와 보관 절차 취소 안내를 띄운다. - 홈 탑바에 알림함과 미읽음 점, 기기 알림이 꺼졌을 때 켜는 배너를 둔다. - 설정 > 알림에 기록 알림 시각·요일·주간 목표, 대리인, 수신인 기념일 화면을 더한다. - 서버가 토큰을 무효(requiresReset)라 하면 프로세스당 한 번 새 FID 를 받아 다시 등록한다. - 알림 API 를 NotificationApiService 로 모으고 Route.Setting 시작점을 SettingStart 로 일반화한다. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
|
열린 PR 중 이 PR 과 같은 파일을 서로 다르게 고친 것이 있다. 어느 쪽이 먼저 머지되든 나중 쪽은 base 를 병합해야 통과한다 (#1750).
머지 자체는 GitHub 이 막는다 — 한쪽이 들어가면 다른 쪽은 CONFLICTING 이 되어 merge queue 에 못 들어간다. 이 코멘트는 리컨사일러가 매 실행 현재 상태로 고쳐 쓴다. 해소되면 |
Sadturtleman
enabled auto-merge
October 27, 2026 08:54
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📌𝘐𝘴𝘴𝘶𝘦𝘴
📎𝘞𝘰𝘳𝘬 𝘋𝘦𝘴𝘤𝘳𝘪𝘱𝘵𝘪𝘰𝘯
BE#317 의 비결제 알림(A~E)·FCM data-only v1 계약(
config/firebase/NOTIFICATION_CONTRACT.md)을 앱이 받아 알림을 그리고, 탭·알림함에서 현재 목적지로 이동하고, 알림 설정을 고칠 수 있게 합니다. 결제(F)와 알림톡·설치 후 목적지 복원은 범위 밖입니다.1. 기기 등록·권한
PushInstallationIdStore, DEVICE 수명·백업 제외)를 만들어PUT users/push-tokens에installationId·notificationPermission을 싣습니다.areNotificationsEnabled()가 바뀌었으면PUT users/push-installations로 보고하고 같은 식별자를 다시 등록합니다. 등록 중복 판정은 (식별자, 권한) 쌍입니다.requiresReset을 실으면 프로세스당 한 번 FID 를 지우고 새로 받아 등록합니다(FCM 대기는 뮤텍스 밖).2. 수신
schemaVersion·destination·ID·action·notificationId를 읽습니다. 모르는schemaVersion이면 홈으로 엽니다.SERVER_ID와 목적지 키만 거른SERVER_DATA를 더했습니다(기존 extra 키 유지).3. 탭·알림함 → 목적지
GET users/notifications/{id}/target으로 현재 목적지를 묻고PATCH …/read로 읽음 처리합니다. 실패·3초 초과면 실어 온 data 로, 그것도 없으면 탭으로 엽니다. 지워진 대상은 목록 + 서버 문구 스낵바입니다.ServerNotificationDestination이 서버 whitelist 전부를 앱 화면으로 옮깁니다.EDIT면 수정 화면을 위에) / COMPOSE일기·깊은 생각 상세는 payload 에 찾을 달이 없어 기록 탭으로 엽니다.
Route.NotificationInbox)과 미읽음 점을 두었습니다. 알림함 탭도 푸시 탭과 같은 진입 큐·목적지 경로를 탑니다.Route.Setting의 시작점을SettingStart로 일반화했습니다(기존 수신인 등록 진입 포함).4. 앱 진입·안내
POST …/notification-preferences/entry를 보냅니다. 쉬운 질문이 오면 시트로 띄우고, 고르면 그 질문을 제목으로 일기를 엽니다. 보관 절차가 취소됐으면 스낵바로 알립니다.5. 설정 > 알림
6. 로컬 데일리 알림 제거
서버 B 와 이중 발송되고 하루 1건 상한·야간 이월을 깨므로
DailyNotificationWorker·스케줄러·관찰자·Konsist 가드를 지우고,LegacyDailyNotification.clear()가 남은 예약과 채널을 지웁니다.검증
ktlintCheck,:konsist:test,:app:core:data:core:common:core:network:core:ui:feature:setting:{data,presentation}:feature:home:presentation:feature:timeletter:presentation:feature:mindrecord:presentation단위 테스트,:app:compileDebugAndroidTestKotlin, 5개 모듈compileDebugScreenshotTestKotlin,:app:core:ui:feature:{setting,home}:presentationlintDebug로컬 통과/target해석·fallback·시간 초과, 진입 보고, FCM v1 payload·Intent 왕복, 알림함·배지, 설정 3화면 ViewModel,LocalTime와이어 변환, API wire 계약🧪 CI Test Plan
{ "androidTest": { "mode": "selected", "reason": "알림 진입 큐가 목적지 조회를 거치도록 바뀌고 Route.Setting 시작점이 SettingStart 로 일반화됐다. 기존 cold·background 알림 진입과 설정 host 시작점·수신인 수정 흐름을 API 34 에서 확인한다.", "tests": [ { "path": "app/src/androidTest/java/com/afternote/afternote_fe/NotificationNavigationAndroidTest.kt", "selector": "com.afternote.afternote_fe.NotificationNavigationAndroidTest#warmNotificationWhileLoggedOut_isReceivedWithoutBypassingOnboarding", "device": "api34" }, { "path": "app/src/androidTest/java/com/afternote/afternote_fe/NotificationNavigationAndroidTest.kt", "selector": "com.afternote.afternote_fe.NotificationNavigationAndroidTest#backgroundNotification_resumesSameActivityAndNavigatesToDestination", "device": "api34" }, { "path": "app/src/androidTest/java/com/afternote/afternote_fe/NotificationColdStartAndroidTest.kt", "selector": "com.afternote.afternote_fe.NotificationColdStartAndroidTest#coldPendingIntentLaunchWhileLoggedIn_opensDestination", "device": "api34" }, { "path": "app/src/androidTest/java/com/afternote/afternote_fe/SettingImplementedCoverageAndroidTest.kt", "selector": "com.afternote.afternote_fe.SettingImplementedCoverageAndroidTest#settingNavHost_startWithRecipientRegistrationOpensRegisterFirstAndBackExitsHost", "device": "api34" }, { "path": "app/src/androidTest/java/com/afternote/afternote_fe/SettingImplementedCoverageAndroidTest.kt", "selector": "com.afternote.afternote_fe.SettingImplementedCoverageAndroidTest#appNavigation_settingRouteArgumentSelectsRegisterAsFirstScreen", "device": "api34" }, { "path": "app/src/androidTest/java/com/afternote/afternote_fe/SettingImplementedCoverageAndroidTest.kt", "selector": "com.afternote.afternote_fe.SettingImplementedCoverageAndroidTest#settingNavHost_passwordChangeEntryAndBackKeepSettingsHost", "device": "api34" }, { "path": "app/src/androidTest/java/com/afternote/afternote_fe/SettingImplementedCoverageAndroidTest.kt", "selector": "com.afternote.afternote_fe.SettingImplementedCoverageAndroidTest#settingNavHost_receiverManageListRowNavigatesToEditWithExactReceiverId", "device": "api34" }, { "path": "app/src/androidTest/java/com/afternote/afternote_fe/SettingImplementedCoverageAndroidTest.kt", "selector": "com.afternote.afternote_fe.SettingImplementedCoverageAndroidTest#settingNavHost_deliveryConditionReceiverSelectionPreservesExactReceiverId", "device": "api34" }, { "path": "app/src/androidTest/java/com/afternote/afternote_fe/SettingImplementedCoverageAndroidTest.kt", "selector": "com.afternote.afternote_fe.SettingImplementedCoverageAndroidTest#settingNavHost_withdrawGuideCancelThenAgreementConfirmPreservesBoundary", "device": "api34" }, { "path": "app/src/androidTest/java/com/afternote/afternote_fe/SettingEditorSaveSignalAndroidTest.kt", "selector": "com.afternote.afternote_fe.SettingEditorSaveSignalAndroidTest#receiverEdit_saveSuccessPopsExactlyOneScreenToReceiverList", "device": "api34" }, { "path": "app/src/androidTest/java/com/afternote/afternote_fe/SettingEditorSaveSignalAndroidTest.kt", "selector": "com.afternote.afternote_fe.SettingEditorSaveSignalAndroidTest#receiverEdit_saveFailureShowsMessageAndStaysOnEdit", "device": "api34" }, { "path": "app/src/androidTest/java/com/afternote/afternote_fe/SettingEditorSaveSignalAndroidTest.kt", "selector": "com.afternote.afternote_fe.SettingEditorSaveSignalAndroidTest#receiverEdit_invalidEmailOrPhoneBlocksSaveWithoutRequest", "device": "api34" }, { "path": "app/src/androidTest/java/com/afternote/afternote_fe/SettingEditorSaveSignalAndroidTest.kt", "selector": "com.afternote.afternote_fe.SettingEditorSaveSignalAndroidTest#deliveryCondition_saveSuccessPopsExactlyOneScreenToReceiverSelection", "device": "api34" } ] } }📷𝘚𝘤𝘳𝘦𝘦𝘯𝘴𝘩𝘰𝘵
새 화면(알림함·쉬운 질문 시트·기록 알림·대리인·기념일·홈 배너)은 기존 디자인 토큰과 설정 컴포넌트로 구성했고 시안은 없습니다. 기존 Preview·스크린샷 대상의 기본 인자는 바꾸지 않았습니다.
💬𝘛𝘰 𝘙𝘦𝘷𝘪𝘦𝘸𝘦𝘳𝘴
ServerNotificationDestination한 곳입니다. 상세 화면 진입점이 늘면 여기만 고치면 됩니다.🤖 Generated with Claude Code