-
Notifications
You must be signed in to change notification settings - Fork 1
[FEAT] 업데이트 공지 바텀시트 #254
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
[FEAT] 업데이트 공지 바텀시트 #254
Conversation
Walkthrough앱 버전 주입 모듈을 추가하고 DataStore–로컬–레포–도메인 계층에 업데이트 공지 상태(다시 보지 않을 버전 / 마지막 노출일) 플로우 및 기록 API를 추가했다. 홈 화면에 업데이트 공지 바텀시트를 구현하고 ViewModel에서 노출 여부를 계산·기록하며 사용자 액션을 처리한다. Coil 의존성 버전도 업그레이드했다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant HomeScreen
participant HomeViewModel
participant UserInfoRepository
participant UserLocalDataSource as LocalDS
participant DataStore
participant AppVersion as AppVersion
HomeScreen->>HomeViewModel: 초기 로드
HomeViewModel->>AppVersion: 주입된 appVersion 사용
HomeViewModel->>UserInfoRepository: updateNoticeDontShowVersionFlow 구독
UserInfoRepository->>LocalDS: 구독 위임
LocalDS->>DataStore: 읽기
DataStore-->>HomeViewModel: 저장된 dontShowVersion
HomeViewModel->>UserInfoRepository: updateNoticeLastShownDateEpochFlow 구독
UserInfoRepository->>LocalDS: 구독 위임
LocalDS->>DataStore: 읽기
DataStore-->>HomeViewModel: 저장된 lastShownDateEpoch
note over HomeViewModel: shouldShow = (savedVersion != appVersion) && (lastShownEpoch != todayEpoch) && isOnline
alt shouldShow == true
HomeViewModel->>UserInfoRepository: markUpdateNoticeShownToday()
UserInfoRepository->>LocalDS: 위임
LocalDS->>DataStore: 오늘 epoch 저장
HomeViewModel-->>HomeScreen: isUpdateNoticeVisible = true
else
HomeViewModel-->>HomeScreen: isUpdateNoticeVisible = false
end
rect rgba(220,240,255,0.6)
User->>HomeScreen: 바텀시트 상호작용
HomeScreen->>HomeViewModel: OnClickDontShowAgain
HomeViewModel->>UserInfoRepository: markUpdateNoticeDontShow(appVersion)
UserInfoRepository->>LocalDS: 위임
LocalDS->>DataStore: dontShowVersion = appVersion 저장
HomeViewModel-->>HomeScreen: isUpdateNoticeVisible = false
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Nitpick comments (15)
feature/home/src/main/res/values/strings.xml (1)
128-129: 문구 추가 OK + 배너 접근성 보완 제안TalkBack을 위해 배너 이미지의 contentDescription 문자열을 추가해 두는 것을 권장합니다.
<string name="update_notice_bottom_sheet_dont_show_again">다시 보지 않기</string> <string name="update_notice_bottom_sheet_close">닫기</string> + <string name="update_notice_banner_content_description">업데이트 안내 배너</string>app/src/main/java/com/yapp/orbit/di/AppVersionModule.kt (1)
11-18: @nAmed 대신 @qualifier 사용 고려문자 키 충돌을 피하려면 커스텀 Qualifier로 교체하는 편이 안전합니다. 현재 구현도 기능상 문제는 없습니다.
- @Named("appVersion") - fun provideAppVersion(): String = BuildConfig.VERSION_NAME + @AppVersion + fun provideAppVersion(): String = BuildConfig.VERSION_NAME추가: Qualifier 정의
import javax.inject.Qualifier @Qualifier @Retention(AnnotationRetention.BINARY) annotation class AppVersionfeature/home/src/main/java/com/yapp/home/HomeContract.kt (1)
62-63: 액션 네이밍 소폭 제안의도 중심으로
OnClickDontShowAgain→MarkDontShowAgain같은 이름을 고려하면 뷰와의 결합도가 더 낮아집니다. 선택 사항입니다.core/datastore/src/main/java/com/yapp/datastore/UserPreferences.kt (2)
119-128: 관찰 플로우 구성 적절
catch(emptyPreferences) + distinctUntilChanged()패턴 좋습니다. 사용 측에서null처리만 유의하면 됩니다. 필요 시 편의 플로우도 고려해 보세요(예:wasShownToday: Flow<Boolean>).
208-218: Clock 주입 권장 — today() 의존성 결정론화
LocalDate.now()를 직접 호출하는 private fun today()는 단위 테스트와 DST/타임존 시나리오에서 비결정적입니다. core/common/di/ClockModule이 이미 있으므로 UserPreferences 등에서 Clock(또는 TimeProvider)을 생성자 주입하고 LocalDate.now(clock).format(...)으로 변경해 고정된 Clock으로 테스트할 수 있게 만드세요.
대상 예: core/datastore/src/main/java/com/yapp/datastore/UserPreferences.kt (today() 정의·사용), data/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSourceImpl.kt, feature/home/src/main/java/com/yapp/home/HomeViewModel.ktdata/src/main/java/com/yapp/data/local/datasource/UserLocalDataSource.kt (1)
9-10: 날짜 포맷 계약 명시 필요.
...LastShownDateFlow: Flow<String?>의 포맷(예: ISO-8601yyyy-MM-dd)을 KDoc로 명시하거나, 차라리LocalDate/epochDays(Int)로 저장하는 편이 안전합니다(파싱/로케일 이슈 회피).저장소 전반에서 동일 포맷을 사용 중인지 확인 부탁드립니다.
feature/home/src/main/java/com/yapp/home/component/bottomsheet/UpdateNoticeBottomSheet.kt (5)
68-74: 플레이스홀더/에러 처리 및 접근성 보강.네트워크 실패/지연 시 공백이 됩니다. 또한 배너가 정보 전달을 포함한다면
contentDescription이 필요합니다.다음 수정을 제안합니다.
+import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.painter.ColorPainter ... - AsyncImage( - model = imageUrl, - contentDescription = null, + AsyncImage( + model = imageUrl, + placeholder = ColorPainter(Color(0xFFEDEDED)), + error = ColorPainter(Color(0xFFEDEDED)), + contentDescription = stringResource(id = R.string.update_notice_bottom_sheet_banner_cd), contentScale = ContentScale.Crop, modifier = Modifier .fillMaxWidth() .aspectRatio(1.0f), )리소스 문자열(
update_notice_bottom_sheet_banner_cd) 추가가 필요합니다.
35-39: 배경 탭 닫기 리플 억제.전면 오버레이 클릭 시 전체 화면 리플이 번쩍일 수 있습니다. 상호작용 흔적이 불필요하므로 indication 제거 권장.
+import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.runtime.remember ... Box( modifier = Modifier .fillMaxSize() - .clickable(onClick = onClose), + .clickable( + onClick = onClose, + indication = null, + interactionSource = remember { MutableInteractionSource() }, + ),
41-56: 중복된 shape 지정 정리.
background(shape=..) + clip(shape=..)가 중복입니다. 하나만으로도 모서리 라운딩은 충분합니다(이미지 영역은 아래에서 별도 clip이 없으므로 background 뒤에 clip만 유지).- .background( - color = OrbitTheme.colors.gray_900, - shape = RoundedCornerShape(topStart = 30.dp, topEnd = 30.dp), - ) - .clip(RoundedCornerShape(topStart = 30.dp, topEnd = 30.dp)), + .clip(RoundedCornerShape(topStart = 30.dp, topEnd = 30.dp)) + .background(OrbitTheme.colors.gray_900),
88-100: 액션 영역 접근성: 최소 터치 타겟/역할(Role) 지정.현재 세로 패딩만으로는 48dp 최소 터치 타겟을 항상 보장하지 못할 수 있고, 스크린리더에 버튼 역할이 명확히 전달되지 않습니다.
+import androidx.compose.ui.semantics.Role ... Box( modifier = Modifier .weight(1f) - .clickable(onClick = onDontShowAgain) - .padding(vertical = 14.dp), + .clickable(role = Role.Button, onClick = onDontShowAgain) + .heightIn(min = 48.dp) + .padding(vertical = 14.dp), ... Box( modifier = Modifier .weight(1f) - .clickable(onClick = onClose) - .padding(vertical = 14.dp), + .clickable(role = Role.Button, onClick = onClose) + .heightIn(min = 48.dp) + .padding(vertical = 14.dp),또는 Material3
TextButton사용을 고려해주세요.Also applies to: 102-114
68-74: 배너 비율 고정(1:1) 재검토.서버 배너가 16:9 등 다른 비율일 수 있습니다. 고정 비율 대신 원본 비율 유지(
aspectRatio제거) 또는 서버/메타데이터로 비율을 주입하는 방식을 검토해주세요.feature/home/src/main/java/com/yapp/home/HomeViewModel.kt (4)
374-393: “오늘 한 번만 노출” 표시에 대한 기록 타이밍 확인 필요.계산 시점에 곧바로
markUpdateBottomSheetShownToday()를 호출하여 “실제 노출” 전에 기록됩니다. 화면 전환/프로세스 종료 등으로 실노출이 없었더라도 당일 재노출이 차단될 수 있습니다. 실제 표시 시점(시트가 Compose 트리에 진입하거나 첫 프레임 그려질 때)으로 기록을 이동하는 것을 권장합니다.UI에서 시트가 실제로 표시됨을 신호하는 이벤트를 추가해 그 시점에 기록할지 논의 부탁드립니다.
382-382: 디버그 로그 가드.릴리스 빌드에서 불필요한 버전/날짜 로그가 남습니다.
if (BuildConfig.DEBUG)가드 또는 로그 제거를 권장합니다.-import android.util.Log +import android.util.Log +import com.yapp.orbit.BuildConfig ... -Log.d("HomeViewModel", "App Version: $appVersion, Don't Show Version: $dontShowVersion, Last Shown Date: $lastShownDate, Today: $today") +if (BuildConfig.DEBUG) { + Log.d("HomeViewModel", "App Version: $appVersion, Don't Show Version: $dontShowVersion, Last Shown Date: $lastShownDate, Today: $today") +}
374-393: 반응형 계산으로 단순화 가능(선택).두 플로우를
combine하여shouldShow를 State로 유지하면 설정 변경(예: 설정 초기화)에도 자연스럽게 반영됩니다. 현재 1회 스냅샷(firstOrNull)은 요구사항상 문제는 없으나, UX 관점에서 개선 여지가 있습니다.
374-403: 단위 테스트 추가 제안.다음 시나리오에 대한 VM 단위 테스트를 제안합니다:
- dontShowVersion == appVersion → 미노출
- lastShownDate == today → 미노출
- 둘 다 조건 불충족 → 노출 및 “오늘 보여줌” 기록
원하시면 테스트 스캐폴딩을 생성해드릴게요.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
app/src/main/java/com/yapp/orbit/di/AppVersionModule.kt(1 hunks)core/datastore/src/main/java/com/yapp/datastore/UserPreferences.kt(3 hunks)data/src/main/java/com/yapp/data/local/datasource/UserLocalDataSource.kt(1 hunks)data/src/main/java/com/yapp/data/local/datasource/UserLocalDataSourceImpl.kt(2 hunks)data/src/main/java/com/yapp/data/repositoryimpl/UserInfoRepositoryImpl.kt(1 hunks)domain/src/main/java/com/yapp/domain/repository/UserInfoRepository.kt(1 hunks)feature/home/build.gradle.kts(1 hunks)feature/home/src/main/java/com/yapp/home/HomeContract.kt(2 hunks)feature/home/src/main/java/com/yapp/home/HomeScreen.kt(2 hunks)feature/home/src/main/java/com/yapp/home/HomeViewModel.kt(5 hunks)feature/home/src/main/java/com/yapp/home/component/bottomsheet/UpdateNoticeBottomSheet.kt(1 hunks)feature/home/src/main/res/values/strings.xml(1 hunks)gradle/libs.versions.toml(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Continuous Deployment
🔇 Additional comments (10)
gradle/libs.versions.toml (1)
53-53: Coil 2.7.0 업그레이드 LGTMCompose(1.7.6)/Kotlin(2.0.0)/AGP(8.7.x) 조합과도 무리 없어 보입니다. 릴리스 브랜치라 이미지 로딩 회귀만 한 번 QA 체크 부탁드립니다.
feature/home/build.gradle.kts (1)
22-22: Coil Compose 의존성 추가 적합
AsyncImage사용 위해 필요한 최소 의존성만 추가되어 좋습니다. 배너가 GIF일 가능성이 있으면libs.coil.gif추가만 검토해 주세요.feature/home/src/main/java/com/yapp/home/HomeContract.kt (1)
21-21: 상태 필드 추가 적절UI 토글을 위한
isUpdateNoticeVisible추가 방향 좋습니다.core/datastore/src/main/java/com/yapp/datastore/UserPreferences.kt (1)
41-43: DataStore 키 추가 OK네이밍 일관성 유지되어 좋습니다. 마이그레이션 이슈도 없어 보입니다.
feature/home/src/main/java/com/yapp/home/HomeScreen.kt (2)
78-78: 필요한 컴포넌트 임포트 OK
250-259: 바텀시트 표출 위치/와이어링 OK + 중첩 시트 상호작용 확인 요청
AlarmListBottomSheet위에 모달로 올라오는 구조로 보이며 액션 바인딩도 적절합니다. 백프레스/외부 탭 dismiss 시HideUpdateNotice가 호출되는지 한 번만 확인 부탁드립니다(이중 시트 제스처 충돌 방지).data/src/main/java/com/yapp/data/local/datasource/UserLocalDataSourceImpl.kt (1)
14-15: 위임 구조 깔끔합니다.
UserPreferences로의 위임이 일관되고 사이드이펙트가 없습니다. LGTM.
UserPreferences.clearUserData()가 새 키들까지 초기화하는지 한 번만 확인 부탁드립니다.Also applies to: 29-35
data/src/main/java/com/yapp/data/repositoryimpl/UserInfoRepositoryImpl.kt (1)
20-21: 위임/노출 일관성 좋습니다.로컬 데이터소스와 1:1 위임으로 유지보수 용이합니다. 별도 이슈 없습니다.
Also applies to: 26-27
feature/home/src/main/java/com/yapp/home/HomeViewModel.kt (2)
35-35: 앱 버전 주입 👍
@Named("appVersion")주입으로 테스트 용이성이 좋아졌습니다.
396-398: “다시 보지 않기” 처리 OK현재 버전으로 명확히 고정 저장하고 즉시 숨기는 흐름이 요구사항에 부합합니다.
data/src/main/java/com/yapp/data/local/datasource/UserLocalDataSource.kt
Outdated
Show resolved
Hide resolved
domain/src/main/java/com/yapp/domain/repository/UserInfoRepository.kt
Outdated
Show resolved
Hide resolved
domain/src/main/java/com/yapp/domain/repository/UserInfoRepository.kt
Outdated
Show resolved
Hide resolved
feature/home/src/main/java/com/yapp/home/component/bottomsheet/UpdateNoticeBottomSheet.kt
Outdated
Show resolved
Hide resolved
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
domain/src/main/java/com/yapp/domain/repository/UserInfoRepository.kt (1)
11-12: 업데이트 공지 관련 도메인 인터페이스 추가업데이트 공지 기능을 위한 새로운 Flow와 메서드들이 적절히 추가되었습니다. epoch 기반 날짜 사용으로 타임존 독립적인 구현이 가능합니다.
feature/home/src/main/java/com/yapp/home/component/bottomsheet/UpdateNoticeBottomSheet.kt (1)
47-48: 배너 URL이 버전에 고정되어 운영 유연성 부족현재 구현은 앱 버전에 따라 고정된 URL 패턴을 사용합니다. PR 설명에는 "서버에서 공지 이미지를 받아 표시"한다고 되어 있으나, 실제로는 클라이언트에서 버전 기반으로 URL을 생성하고 있습니다. 이는 다음과 같은 문제를 야기할 수 있습니다:
- 배너 이미지 변경 시 서버 파일 교체만으로는 불가능
- A/B 테스트나 긴급 공지 변경이 어려움
- 버전별로 이미지 경로가 고정되어 유연성 부족
서버 API나 Remote Config를 통해 동적으로 이미지 URL을 받아오는 방식으로 개선을 권장합니다.
🧹 Nitpick comments (7)
app/src/main/AndroidManifest.xml (1)
14-14: 중복된 권한 선언 제거 필요
ACCESS_NETWORK_STATE권한이 Line 5와 Line 14에 중복으로 선언되어 있습니다. Line 14의 중복 선언을 제거해주세요.<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" /> - <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>feature/home/src/main/java/com/yapp/home/HomeViewModel.kt (3)
378-400: 업데이트 공지 노출 로직 — 예외 내성 보강 제안DataStore 쓰기 실패 시 크래시/중단 방지를 위해 기록 부분을 runCatching으로 감싸면 안전합니다. 또한 최초 1회만 호출되므로 네트워크가 회복돼도 노출되지 않습니다(의도된 동작인지 확인 필요).
다음 정도로 보강을 권합니다.
val shouldShow = when { dontShowVersion != null && dontShowVersion == appVersion -> false lastShownDate != null && lastShownDate == today -> false else -> true } - if (shouldShow) userInfoRepository.markUpdateNoticeShownToday() + if (shouldShow) { + runCatching { userInfoRepository.markUpdateNoticeShownToday() } + .onFailure { e -> Log.w("HomeViewModel", "Failed to mark update notice shown", e) } + } reduce { state.copy(isUpdateNoticeVisible = shouldShow) }네트워크 재시도 필요 시, Connectivity 상태를 Flow로 노출해 재구독 트리거를 거는 방식을 고려해주세요.
402-405: '다시 보지 않기' 처리 — LGTM, 실패 처리만 보완 권장기록 후 즉시 숨김 처리 흐름은 적절합니다. 동일하게 runCatching으로 예외 로깅을 추가하면 더 안전합니다.
- userInfoRepository.markUpdateNoticeDontShow(appVersion) + runCatching { userInfoRepository.markUpdateNoticeDontShow(appVersion) } + .onFailure { e -> Log.w("HomeViewModel", "Failed to mark dont-show version", e) }
457-464: 온라인 판별 방식 개선 여지단발성 체크만으로는 재연결 시점 반영이 어렵습니다. 필요하다면 ConnectivityManager.registerDefaultNetworkCallback 기반 Flow로 상태를 스트림화하는 유틸로 추출을 권장합니다.
domain/src/main/java/com/yapp/domain/repository/FortuneRepository.kt (1)
9-9: KDoc 제안: 'epoch day' 기준 명시Long 값이 UTC/로컬 기준 epoch‑day인지 인터페이스에 주석을 추가하면 오용을 줄일 수 있습니다.
feature/mission/src/main/java/com/yapp/mission/MissionViewModel.kt (1)
137-157: 미션 완료 후 내비게이션 조건 — LGTM, 가독성 소폭 개선 제안조건식은 의도대로 보입니다. 불변식 추출로 읽기성만 다듬으면 좋습니다.
- val shouldOpenFortune = ( - fortuneCreateStatus is FortuneCreateStatus.Creating || - fortuneCreateStatus is FortuneCreateStatus.Success && hasUnseenFortune - ) + val creating = fortuneCreateStatus is FortuneCreateStatus.Creating + val successAndUnseen = fortuneCreateStatus is FortuneCreateStatus.Success && hasUnseenFortune + val shouldOpenFortune = creating || successAndUnseendata/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSourceImpl.kt (1)
36-36: Clock 주입으로 테스트/타임존 안정성 확보
LocalDate.now()대신Clock을 주입해 결정적·테스트 가능한 시간을 사용하세요.- private fun todayEpoch(): Long = LocalDate.now().toEpochDay() + private fun todayEpoch(): Long = LocalDate.now(clock).toEpochDay()추가 변경(파일 외): 생성자와 import에
Clock을 포함하고 Hilt 모듈에서@Provides fun provideClock(): Clock = Clock.systemDefaultZone()를 제공하세요.import java.time.Clock class FortuneLocalDataSourceImpl @Inject constructor( private val userPreferences: UserPreferences, private val clock: Clock, ) : FortuneLocalDataSource { ... }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
project.dot.pngis excluded by!**/*.png
📒 Files selected for processing (15)
app/src/main/AndroidManifest.xml(1 hunks)core/datastore/src/main/java/com/yapp/datastore/UserPreferences.kt(7 hunks)data/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSource.kt(1 hunks)data/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSourceImpl.kt(2 hunks)data/src/main/java/com/yapp/data/local/datasource/UserLocalDataSource.kt(1 hunks)data/src/main/java/com/yapp/data/local/datasource/UserLocalDataSourceImpl.kt(2 hunks)data/src/main/java/com/yapp/data/repositoryimpl/FortuneRepositoryImpl.kt(1 hunks)data/src/main/java/com/yapp/data/repositoryimpl/UserInfoRepositoryImpl.kt(1 hunks)domain/src/main/java/com/yapp/domain/repository/FortuneRepository.kt(1 hunks)domain/src/main/java/com/yapp/domain/repository/UserInfoRepository.kt(1 hunks)feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/snooze/AlarmSnoozeTimerViewModel.kt(1 hunks)feature/home/src/main/AndroidManifest.xml(1 hunks)feature/home/src/main/java/com/yapp/home/HomeViewModel.kt(10 hunks)feature/home/src/main/java/com/yapp/home/component/bottomsheet/UpdateNoticeBottomSheet.kt(1 hunks)feature/mission/src/main/java/com/yapp/mission/MissionViewModel.kt(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- data/src/main/java/com/yapp/data/repositoryimpl/UserInfoRepositoryImpl.kt
- data/src/main/java/com/yapp/data/local/datasource/UserLocalDataSource.kt
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-14T15:32:44.064Z
Learnt from: DongChyeon
PR: YAPP-Github/Orbit-Android#252
File: domain/src/main/java/com/yapp/domain/repository/FortuneRepository.kt:16-17
Timestamp: 2025-09-14T15:32:44.064Z
Learning: Fortune creation requests have at least a 1-minute gap between them in the Orbit Android app, making atomic guards for race condition prevention unnecessary in the fortune creation flow.
Applied to files:
data/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSourceImpl.ktcore/datastore/src/main/java/com/yapp/datastore/UserPreferences.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Continuous Deployment
🔇 Additional comments (18)
feature/home/src/main/AndroidManifest.xml (1)
3-3: 네트워크 상태 체크 권한 추가 확인업데이트 공지 바텀시트의 온라인 상태 체크를 위한 권한 추가가 적절합니다.
data/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSource.kt (1)
8-8: 날짜 표현 타입 변경 확인
fortuneDateFlow를fortuneDateEpochFlow로 변경하여Long?타입의 epoch day를 사용하도록 개선되었습니다. 타임존 이슈를 방지하고 날짜 비교를 단순화하는 좋은 변경입니다.feature/home/src/main/java/com/yapp/home/component/bottomsheet/UpdateNoticeBottomSheet.kt (3)
33-45: 버전 정보 획득 시 예외 처리 적절
resolveVersionName함수에서 버전 정보를 안전하게 가져오고, 실패 시 빈 문자열을 반환하는 처리가 잘 되어 있습니다.
58-61: Preview 모드와 런타임 분기 처리 적절
LocalInspectionMode를 활용하여 프리뷰와 실제 런타임을 구분하고, 각각 적절한 버전명과 이미지 URL을 설정하는 처리가 잘 되어 있습니다.
79-96: 프리뷰와 실제 이미지 렌더링 분기 처리 적절프리뷰 모드에서는 흰색 박스를, 실제 런타임에서는 AsyncImage로 배너를 표시하는 분기 처리가 깔끔합니다.
core/datastore/src/main/java/com/yapp/datastore/UserPreferences.kt (5)
29-29: Fortune 날짜를 epoch day로 변경하여 타임존 문제 해결
FORTUNE_DATE에서FORTUNE_DATE_EPOCH로 변경하여 Long 타입의 epoch day를 사용하는 것은 타임존 독립적이고 날짜 비교가 간단해지는 좋은 개선입니다.
40-41: 업데이트 공지 관련 새로운 preference key 추가업데이트 공지 기능을 위한
UPDATE_NOTICE_DONT_SHOW_VERSION과UPDATE_NOTICE_LAST_SHOWN_DATE_EPOCH키가 적절히 추가되었습니다. epoch 기반 날짜 사용으로 일관성을 유지하고 있습니다.
44-44: todayEpoch 헬퍼 함수로 날짜 처리 일관성 확보
LocalDate.now().toEpochDay()를 사용하는 private 헬퍼 함수로 오늘 날짜를 epoch day로 변환하는 로직을 중앙화한 것이 좋습니다.
194-201: 업데이트 공지 관련 마킹 함수 구현 적절
markUpdateNoticeDontShow와markUpdateNoticeShownToday함수가 DataStore에 적절히 값을 저장하도록 구현되었습니다. 특히markUpdateNoticeShownToday에서 현재 날짜를 epoch day로 저장하는 것이 일관성 있습니다.
148-161: Fortune 생성 시 날짜 기반 중복 체크 로직 개선
markFortuneCreated에서 epoch day 기반으로 오늘의 새로운 fortune인지 확인하고, 필요시 SEEN과 TOOLTIP_SHOWN을 초기화하는 로직이 잘 구현되었습니다. 이전에 학습한 내용대로 fortune 생성 요청 간 최소 1분의 간격이 있어 race condition 방지를 위한 atomic guard는 불필요합니다.data/src/main/java/com/yapp/data/local/datasource/UserLocalDataSourceImpl.kt (2)
14-15: 위임 구조 적절 — API 추가 LGTMDataStore의 Flow를 그대로 노출하는 위임이 명확합니다. 네이밍(…EpochFlow)도 다른 모듈과 일관적입니다.
29-35: clearUserData가 업데이트 공지 키들을 초기화함 — 확인됨
core/datastore/src/main/java/com/yapp/datastore/UserPreferences.kt의 clearUserData()가 dataStore.edit { it.clear() }를 호출하므로 updateNoticeDontShowVersion 및 updateNoticeLastShownDateEpoch 키가 삭제됩니다.feature/home/src/main/java/com/yapp/home/HomeViewModel.kt (2)
343-346: Epoch‑day 전환 일관성 확인 — LGTMLocalDate.now().toEpochDay()와 fortuneDateEpochFlow 비교로 전환이 잘 반영되었습니다. 관련 의존 모듈도 동일 기준(로컬 타임존)인지 유지해주세요.
Also applies to: 356-356, 359-359
38-40: appVersion DI 제공자 확인 — 테스트 바인딩 미확인app/src/main/java/com/yapp/orbit/di/AppVersionModule.kt 에서 @nAmed("appVersion") 제공자(provideAppVersion() = BuildConfig.VERSION_NAME)를 확인했습니다. 레포지토리의 test/androidTest 소스에서 해당 바인딩을 대체하거나 @bindvalue로 주입하는 코드(@TestInstallIn / @UninstallModules / @bindvalue 등)는 발견되지 않았습니다. 테스트 환경에서 바인딩 필요 시 @TestInstallIn으로 대체하거나 테스트별로 @UninstallModules + 테스트 모듈 또는 @bindvalue를 추가해 주세요.
feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/snooze/AlarmSnoozeTimerViewModel.kt (1)
47-49: Epoch‑day 마이그레이션 반영 — LGTM단순 치환 정확합니다. 로컬 타임존 기준 비교도 홈 모듈과 일관적입니다.
data/src/main/java/com/yapp/data/repositoryimpl/FortuneRepositoryImpl.kt (1)
18-18: 데이터 소스 매핑 업데이트 — LGTMfortuneDateEpochFlow 위임이 올바르게 반영되었습니다.
domain/src/main/java/com/yapp/domain/repository/FortuneRepository.kt (1)
9-13: 해결: Public API 변경(브레이킹) 검증 완료 — 호출부/구현부 모두 갱신됨domain에 추가된 fortuneDateEpochFlow/hasUnseenFortuneFlow가 core/datastore(UserPreferences), data/local(FortuneLocalDataSourceImpl), data/repositoryimpl(FortuneRepositoryImpl) 및 소비처(HomeViewModel, AlarmSnoozeTimerViewModel, MissionViewModel, AlarmInteractionActivityReceiver)에서 모두 반영되어 기존 참조(fortuneDateFlow)는 없습니다.
data/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSourceImpl.kt (1)
15-15: epoch 기반 전환 LGTM — 레거시 fortuneDateFlow 사용처 없음 확인레포 전체 검색 결과 'fortuneDateFlow'는 발견되지 않았고, 관련 참조는 모두 'fortuneDateEpochFlow'로 통일되어 있습니다. 주요 파일: domain/src/main/java/com/yapp/domain/repository/FortuneRepository.kt, data/src/main/java/com/yapp/data/repositoryimpl/FortuneRepositoryImpl.kt, data/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSourceImpl.kt, core/datastore/src/main/java/com/yapp/datastore/UserPreferences.kt, feature/home/src/main/java/com/yapp/home/HomeViewModel.kt, feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/snooze/AlarmSnoozeTimerViewModel.kt.
Related issue 🛠
closed #253
어떤 변경사항이 있었나요?
CheckPoint ✅
PR이 다음 요구 사항을 충족하는지 확인하세요.
Work Description ✏️
Uncompleted Tasks 😅
To Reviewers 📢
Summary by CodeRabbit
New Features
Improvements