Conversation
โฆ๋ฐฑ๊ทธ๋ผ์ด๋ ์์ ์ฒ๋ฆฌ
โฆ-status [REFACTOR] ์ด์ธ ์์ฑ ์ํ ๊ด๋ฆฌ์ฉ FortuneCreateStatusFlow ๋์
โฆom-sheet [FEAT] ์ ๋ฐ์ดํธ ๊ณต์ง ๋ฐํ ์ํธ
Pre-merge checks and finishing touchesโ Failed checks (1 warning)
โ Passed checks (2 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 |
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and canโt be posted inline due to platform limitations.
โ ๏ธ Outside diff range comments (7)
core/network/src/main/java/com/yapp/network/di/NetworkModule.kt (2)
41-50: ํ์์์ 300์ด๋ ๊ณผ๋ โ ์คํจ ๊ฐ์ง ์ง์ฐ/๋ฆฌ์์ค ์ ์ ์ฆ๊ฐ๋ณดํธ๊ฐ์ผ๋ก๋ ๊ณผํฉ๋๋ค. ์ผ๋ฐ API๋ ๋ ์งง๊ฒ, ๋์ฉ๋ ์ /๋ค์ด๋ก๋๋ง per-call๋ก ๋๋ฆฌ๋ ๊ฒ ์์ ํฉ๋๋ค. ์ด ํธ์ถ ์ ํ์ ์ํด callTimeout๋ ๊ณ ๋ คํด ์ฃผ์ธ์.
- .readTimeout(300, TimeUnit.SECONDS) - .writeTimeout(300, TimeUnit.SECONDS) - .connectTimeout(300, TimeUnit.SECONDS) + .connectTimeout(15, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS) + .callTimeout(60, TimeUnit.SECONDS)
41-50: ๊ธด๊ธ: ์ธ์ฆ Interceptor/Authenticator ๋๋ฝ โ ๋ณดํธ API ์คํจ(๋ธ๋ก์ปค), ์ฆ์ ๋ณต๊ตฌ ํ์core/network/src/main/java/com/yapp/network/di/NetworkModule.kt์ provideHttpClient(๋ผ์ธ 41โ49)์์ OkHttpClient์ loggingInterceptor๋ง ๋ฑ๋ก๋์ด ์์ผ๋ฉฐ, ์ ์ฅ์(.kt/.java) ์ ์ฒด ๊ฒ์ ๊ฒฐ๊ณผ addInterceptor/.authenticator ํธ์ถ ๋ฐ Authorization ํ ํฐ ์ฃผ์ ํ์ ์ด ๋ฐ๊ฒฌ๋์ง ์์ โ ๋ณดํธ API๋ Authorization ํค๋๊ฐ ์์ผ๋ฉด 401/์คํจ ๋ฐ์.
์กฐ์น(๊ถ์ฅ): provideHttpClient์ ์ธ์ฆ Interceptor ๋ฐ/๋๋ Authenticator ์์กด์ฑ ์ฃผ์ ํ Builder์ ์ ์ฉ(์: optional authInterceptor/authenticator ํ๋ผ๋ฏธํฐ ํ addInterceptor/authenticator ํธ์ถ) ๋ฐ ํ ํฐ ์ฃผ์ ยท401 ์ฌ๋ฐ๊ธ ๋ก์ง ์ ์ ๋์ ํ์ธ.feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingViewModel.kt (1)
134-147: ๋น ์ฌ์ด๋ ๋ชฉ๋ก ์ IndexOutOfBoundsException ์ํ.sounds๊ฐ ๋น ๋ฆฌ์คํธ๋ฉด index 0 ์ ๊ทผ์์ ํฌ๋์๊ฐ ๋ฉ๋๋ค. ์์ ๊ฐ๋๋ฅผ ์ถ๊ฐํ์ธ์.
๋ค์์ฒ๋ผ ๊ธฐ๋ณธ ์ ํ ๋ก์ง์ ์์ ํ๊ฒ ๋ฐ๊พธ๋ ๊ฒ์ ์ ์ํฉ๋๋ค.
- alarmUseCase.getAlarmSounds().onSuccess { sounds -> - val defaultSoundIndex = sounds.indexOfFirst { it.title == "Homecoming" }.takeIf { it >= 0 } ?: 0 - val defaultSoundUri = sounds[defaultSoundIndex] + alarmUseCase.getAlarmSounds().onSuccess { sounds -> + val defaultSound = sounds.firstOrNull { it.title == "Homecoming" } ?: sounds.firstOrNull() + if (defaultSound == null) { + Log.w("OnboardingViewModel", "No alarm sounds available; skip creating alarm") + return@onSuccess + }๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ๋ถ:
- soundUri = "${defaultSoundUri.uri}", + soundUri = defaultSound.uri,feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingGenderScreen.kt (1)
73-79: ์ ํ ์ด๋ฒคํธ ๋ก๊น ์ด ๋๋ฝ๋์์ต๋๋ค (logEvent ๋ฏธ์ฃผ์ ).OnboardingGenderScreen์ logEvent ํ๋ผ๋ฏธํฐ๊ฐ ๊ธฐ๋ณธ๊ฐ ๋น ๋๋ค์ฌ์ ์ฑ๋ณ ์ ํ ๋ก๊ทธ๊ฐ ์ฌ๋ผ์ง๋๋ค. Route์์ ์ฃผ์ ํ์ธ์.
๋ค์๊ณผ ๊ฐ์ด ์ฃผ์ ์ ๊ถ์ฅํฉ๋๋ค.
OnboardingGenderScreen( state = state, bottomSheetState = bottomSheetState, currentStep = 5, totalSteps = 6, processAction = viewModel::processAction, + logEvent = analyticsHelper::logEvent, )feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/AlarmInteractionActivity.kt (1)
102-105: API 33 ์ ์ฉ registerReceiver ์ค๋ฒ๋ก๋ ์ฌ์ฉ์ผ๋ก ํ์ OS์์ ํฌ๋์ ๋ฐ์RECEIVER_EXPORTED ํ๋๊ทธ๋ฅผ ๋ฐ๋ 3-์ธ์ ์ค๋ฒ๋ก๋๋ Android 13(API 33)+ ์ ์ฉ์ ๋๋ค. ํ์ฌ ์ฝ๋ ๊ทธ๋๋ก๋ฉด API 32 ์ดํ์์ NoSuchMethodError๋ก ํฌ๋์๊ฐ ๋ฉ๋๋ค. SDK ๊ฐ๋๋ก ๋ถ๊ธฐํด ์ฃผ์ธ์.
private fun registerAlarmInteractionActivityCloseReceiver() { val filter = IntentFilter(AlarmConstants.ACTION_ALARM_INTERACTION_ACTIVITY_CLOSE) - registerReceiver(broadcastReceiver, filter, RECEIVER_EXPORTED) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + registerReceiver(broadcastReceiver, filter, RECEIVER_EXPORTED) + } else { + @Suppress("DEPRECATION") + registerReceiver(broadcastReceiver, filter) + } }core/common/src/main/java/com/yapp/common/navigation/route/MissionRoute.kt (1)
3-3: ์๋ชป๋ import๋ก ์ปดํ์ผ ์คํจ ๊ฐ๋ฅ์ฑMissionMode๋
com.yapp.domain.modelํจํค์ง๋ก ๋ณด์ ๋๋ค. import ๊ฒฝ๋ก๋ฅผ ์์ ํด ์ฃผ์ธ์.-import com.yapp.domain.MissionMode +import com.yapp.domain.model.MissionModefeature/home/src/main/java/com/yapp/home/HomeScreen.kt (1)
295-299: LocalDensity ์บก์ฒ ๋๋ฝ์ผ๋ก ์ปดํ์ผ ์๋ฌ ์ ๋ฐ.์๋์์
placeable.height.toDp()๋ฅผ ํธ์ถํ์ง๋งDensity์ค์ฝํ๊ฐ ์์ด ์ปดํ์ผ์ ์คํจํฉ๋๋ค.LocalDensity.current๋ฅผ ์บก์ฒํด ์ฌ์ฉํด ์ฃผ์ธ์.var sheetHalfExpandHeight by remember { mutableStateOf(0.dp) } + val density = LocalDensity.current
๐งน Nitpick comments (70)
feature/home/src/main/java/com/yapp/home/alarm/addedit/AlarmAddEditScreen.kt (4)
308-316: ํ๋์ฝ๋ฉ๋ 20.dp ๋ฐ๋ณต ์ต์ํ๋์ผํ ์ํ ํจ๋ฉ ๊ฐ์ด ์ฌ๋ฌ ๊ณณ์์ ๋ฐ๋ณต๋ฉ๋๋ค. ๋ก์ปฌ ์์๋ก ์ถ์ถํด ์ ์ง๋ณด์์ฑ์ ๋์ด๋ฉด ์ข๊ฒ ์ต๋๋ค.
์๋์ฒ๋ผ ๊ฐ๋จํ ์ ๋ฆฌํ ์ ์์ต๋๋ค:
@@ - OrbitBottomSheetLayout(sheetState = bottomSheetState) { - Column( + OrbitBottomSheetLayout(sheetState = bottomSheetState) { + val contentHorizontalPadding = 20.dp + Column( @@ - AlarmAddEditSelectDaysSection( - modifier = Modifier.padding(horizontal = 20.dp), + AlarmAddEditSelectDaysSection( + modifier = Modifier.padding(horizontal = contentHorizontalPadding), @@ - AlarmAddEditSettingsSection( - modifier = Modifier.padding(horizontal = 20.dp), + AlarmAddEditSettingsSection( + modifier = Modifier.padding(horizontal = contentHorizontalPadding), @@ - .padding( - start = 20.dp, - end = 20.dp, + .padding( + start = contentHorizontalPadding, + end = contentHorizontalPadding, bottom = 12.dp, ),Also applies to: 325-329
286-286: ๋ค๋น๊ฒ์ด์ ๋ฐ ํจ๋ฉ ์ค๋ณต ์ฌ์ง
OrbitBottomSheetLayout์ด ๋ด๋ถ์์navigationBarsPadding()์ ์ ์ฉํ๋ฏ๋ก, ์ ์ฅ ๋ฒํผ์bottom = 12.dp์ ํฉ์ณ์ ธ ์ผ๋ถ ๊ธฐ๊ธฐ(3โbutton ๋ด๋น๊ฒ์ด์ ๋ฑ)์์ ์ง๋์น๊ฒ ํฐ ํ๋จ ์ฌ๋ฐฑ์ด ์๊ธธ ์ ์์ต๋๋ค. UX์ธก ํ์ธ ํ ํ์ ์ ๋ฒํผ ์ปจํ ์ด๋์๋imePadding()๋ง ์ถ๊ฐํ๊ฑฐ๋, ํ๋จ ์ฌ๋ฐฑ์ ์กฐ๊ฑด๋ถ๋ก ์ค์ด๋ ๊ฒ์ ๊ณ ๋ คํด ์ฃผ์ธ์.Also applies to: 321-329
321-324: ์ ์ฅ ๋ฒํผ ํ์ฑํ ์กฐ๊ฑด ์ฐ๋ ์ ์ํญ์
enabled = true๋ก ๋์ด ์์ด ๋น์ ์ ์ ๋ ฅ/๋ฏธ๋ณ๊ฒฝ ์ํ์์๋ ์ ์ฅ ๊ฐ๋ฅํ ์ ์์ต๋๋ค. ์ ํจ์ฑ/๋ณ๊ฒฝ ์ฌ๋ถ ํ๋๊ทธ๊ฐ ์๋ค๋ฉด ์ฐ๋์ ๊ถ์ฅํฉ๋๋ค(์:enabled = state.isSaveEnabled).
288-331: ์ํ ํ๋ฉด/ํฐํธ ํ๋ํ ํ๊ฒฝ์์์ ์คํฌ๋กค ๊ฐ๋ฅ์ฑ ๊ฒํํ์ฌ ๋ฃจํธ
Column์ ์คํฌ๋กค์ด ์์ด, ๋ด์ฉ์ด ๊ธธ์ด์ง๋ ์ํ(์ธ์ด/ํฐํธ ์ค์ผ์ผ, ์์คํ ์ ์ค์ฒ ์์ญ ํฉ์ฐ)์์ ํ๋จ ๋ฒํผ์ด ๊ฐ๋ ค์ง ์ ์์ต๋๋ค. ์ฌ์ ๊ฐ ์๋ค๋ฉดLazyColumn์ ํ ํน์ ์น์ ๋ณ ์คํฌ๋กค ์ฒ๋ฆฌ ๊ฒํ ๋ฅผ ์ ์ํฉ๋๋ค.feature/home/src/main/java/com/yapp/home/component/bottomsheet/AlarmListBottomSheet.kt (1)
326-331: ๋ ๊ฐ์ DropdownMenu๊ฐ ๋์์ ์ด๋ฆด ์ ์๋ ์ํ ๊ณต๊ฐ์ด์ ํญ์ Compose ํธ๋ฆฌ์ ์กด์ฌํ๋ฏ๋ก menuExpanded์ sortDropDownMenuExpanded๊ฐ ๋์์ true๊ฐ ๋๋ฉด ๋ ๋ฉ๋ด๊ฐ ๊ฒน์ณ ์ด๋ฆด ์ ์์ต๋๋ค. ํธ์ถ ์ธก ๋ถ๋ณ์์ผ๋ก ์ํธ ๋ฐฐํ๋ฅผ ๋ณด์ฅํ์ง ์๋๋ค๋ฉด, ๋จ์ผ ์ํ๋ก ํตํฉํ๋ ํธ์ด ์์ ํฉ๋๋ค.
๊ฐ๋จ ์ ์:
- ๋จ์ผ ์ํ๋ก ํตํฉ: enum class Menu { None, Main, Sort }๋ฅผ ์ฌ์ฉํ๊ณ expanded = (menu == Main/Sort)๋ก ์ ์ด.
- ํน์ onClickSort์์ ๋ฐ๋์ menuExpanded=false๋ฅผ ๋ณด์ฅ.
ํธ์ถ๋ถ์์ ๋ ๋ถ๋ฆฐ์ ๋์์ true๋ก ๋ง๋ค์ง ์๋ ๋ก์ง์ด ์๋์ง ํ์ธํด์ฃผ์ธ์. ์์ผ๋ฉด ์ ๋ฆฌํฉํฐ๋ฅผ ๊ถ์ฅํฉ๋๋ค.
Also applies to: 333-338
data/src/main/java/com/yapp/data/remote/di/ServiceModule.kt (1)
16-17: ๋ฉ์๋ ๋ค์ด๋ฐ ์ผ๊ด์ฑ(nit): provideโฆ ํํ ๊ถ์ฅHilt ๊ด๋ก์ provideXxx๋ก ๋ง์ถ๋ฉด ๊ฐ๋ ์ฑ์ด ์ข์์ง๋๋ค.
- fun providesApiService(retrofit: Retrofit): ApiService = + fun provideApiService(retrofit: Retrofit): ApiService =core/network/src/main/java/com/yapp/network/di/NetworkModule.kt (3)
54-63: kotlinx.serialization ์ปจ๋ฒํฐ Optโin ํ์ ๊ฐ๋ฅ์ฑํ๋ก์ ํธ ์ค์ ์ ๋ฐ๋ผ asConverterFactory ์ฌ์ฉ ์ ExperimentalSerializationApi Optโin์ด ํ์ํ ์ ์์ต๋๋ค. ์ปดํ์ผ ๊ฒฝ๊ณ /์๋ฌ๊ฐ ๋ณด์ธ๋ค๋ฉด ์๋์ฒ๋ผ ๋ช ์ Optโin ํด ์ฃผ์ธ์.
- fun provideRetrofit( + @OptIn(kotlinx.serialization.ExperimentalSerializationApi::class) + fun provideRetrofit( okHttpClient: OkHttpClient, buildConfigFieldProvider: BuildConfigFieldProvider, json: Json, ): Retrofit =
54-63: ๋นโJSON/๋น ์๋ต ๋๋น: Scalars ์ปจ๋ฒํฐ ์ ๋ฑ๋ก ๊ถ์ฅ์๋ฒ๊ฐ text/plain ๋๋ ๋น ๋ฐ๋(204/200 without body)๋ฅผ ๋ฐํํ๋ ์๋ํฌ์ธํธ๊ฐ ์๋ค๋ฉด JSON ์ปจ๋ฒํฐ๋ง์ผ๋ก๋ ์คํจํ ์ ์์ต๋๋ค. ํ์ ์ ScalarsConverterFactory๋ฅผ JSON๋ณด๋ค ๋จผ์ ์ถ๊ฐํด ์ฃผ์ธ์.
Retrofit.Builder() - .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) + .addConverterFactory(retrofit2.converter.scalars.ScalarsConverterFactory.create()) + .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) .baseUrl(buildConfigFieldProvider.get().baseUrl) .client(okHttpClient) .build()
54-63: baseUrl ํธ๋ ์ผ๋ง ์ฌ๋์ ๋ณด์ฅRetrofit์ baseUrl์ด ๋ฐ๋์ '/'๋ก ๋๋์ผ ํฉ๋๋ค. BuildConfig ๊ฐ์ด ๋ณด์ฅ๋์ง ์์ผ๋ฉด ๋ฐํ์ ์์ธ๊ฐ ๋ฉ๋๋ค. ๋ฐฉ์ด ์ฝ๋ ์ถ๊ฐ๋ฅผ ๊ถ์ฅํฉ๋๋ค.
- .baseUrl(buildConfigFieldProvider.get().baseUrl) + .baseUrl( + buildConfigFieldProvider.get().baseUrl.let { + if (it.endsWith("/")) it else "$it/" + } + )feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingGenderScreen.kt (2)
168-168: ํ๋์ฝ๋ฉ๋ ๋ฒํผ ๋ผ๋ฒจ i18n ์ฒ๋ฆฌ ํ์.๋ค๊ตญ์ด ๋ฐ ์ ๊ทผ์ฑ ์ผ๊ด์ฑ์ ์ํด stringResource ์ฌ์ฉ์ ๊ถ์ฅํฉ๋๋ค.
๋ฆฌ์์ค ํค๋ ํ๋ก์ ํธ ์ํฉ์ ๋ง๊ฒ ๊ต์ฒดํ์ธ์.
- buttonLabel = "๋ค์", + buttonLabel = stringResource(id = R.string.common_button_next),
190-206: UI ๋ผ๋ฒจ์ ์ํ ๊ฐ์ผ๋ก ์ง์ ์ ์ฅ/๋น๊ตํ๋ ํจํด์ i18n/๋๋ฉ์ธ ์ผ๊ด์ฑ์ ์ทจ์ฝํฉ๋๋ค.ํ์ ๋ฌธ์์ด(๋จ์ฑ/์ฌ์ฑ) ๋์ ๋๋ฉ์ธ ์ฝ๋(์: "MALE"/"FEMALE" ๋๋ enum)๋ฅผ ์ํ์ ๋ณด๊ดํ๊ณ , ๋ผ๋ฒจ์ stringResource๋ก ๋งคํํ์ธ์.
๊ตญ์ ํ์ ์๋ฒ ์คํค๋ง ๋ณ๊ฒฝ์ ๊ฐํ ํํ๋ก ๋ค์๊ณผ ๊ฐ์ด ๊ฐ์ ์ ์ ์ํฉ๋๋ค.
- listOf("๋จ์ฑ", "์ฌ์ฑ").forEach { gender -> + listOf( + "MALE" to stringResource(R.string.gender_male), + "FEMALE" to stringResource(R.string.gender_female), + ).forEach { (genderCode, genderLabel) -> Box(modifier = Modifier.weight(1f)) { OrbitGenderToggle( - label = gender, - isSelected = state.selectedGender == gender, + label = genderLabel, + isSelected = state.selectedGender == genderCode, onToggle = { logEvent( AnalyticsEvent( type = "onboarding_gender_select", properties = mapOf( - AnalyticsEvent.OnboardingPropertiesKeys.GENDER to gender, + AnalyticsEvent.OnboardingPropertiesKeys.GENDER to genderCode, ), ), ) - processAction(OnboardingContract.Action.UpdateGender(gender)) + processAction(OnboardingContract.Action.UpdateGender(genderCode)) }, ) } }๋ฆฌ์์ค ํค(R.string.gender_male/female)๋ ์ค์ ํ๋ก์ ํธ ํค๋ก ๊ต์ฒด ๋ฐ๋๋๋ค.
feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/action/AlarmActionContract.kt (1)
17-18: Boolean? โ Boolean์ผ๋ก ๋จ์ํํ๊ณ null ๊ฒ์ดํ ์ ๊ฑฐ ์ ์์ด๊ธฐ ๋ก๋ฉ์
initialLoading๋ก ์ด๋ฏธ ๊ฐ๋ ค์ง๋ฏ๋กshouldShowMissionStart์ ์ผ์ค ์ํ(null/true/false)๋ ๋ถํ์ํฉ๋๋ค. ๋ถ๋ณ(Boolean)๋ก ์ขํ ํ์ ์์ ์ฑ๊ณผ ๋ถ๊ธฐ ๋จ์ํ๋ฅผ ๊ฐ์ ธ๊ฐ๋ฉด ์ข๊ฒ ์ต๋๋ค.์๋์ฒ๋ผ ๋ณ๊ฒฝ ์, ํ๋ฉด ์ชฝ์
isFirstMission != null๋ถ๊ธฐ๋ ์ ๊ฑฐ ๊ฐ๋ฅํฉ๋๋ค.- val shouldShowMissionStart: Boolean? = null, + val shouldShowMissionStart: Boolean = false,ํ๋ฉด ๋ฐ์(๋ค๋ฅธ ํ์ผ)๋ ํจ๊ป ํ์ํฉ๋๋ค:
- isFirstMission: Boolean?, + shouldShowMissionStart: Boolean,๋ฐ ๋ฒํผ ๋ ๋๋ง์์ null ๋ถ๊ธฐ ์ ๊ฑฐ.
feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/action/AlarmActionScreen.kt (5)
115-126: ํ๋ผ๋ฏธํฐ ๋ช /ํ์ ์ ์ํ์ ์ผ์นํ๋๋ก ์ ๋ฆฌ์ปดํฌ์ ๋ธ ํ๋ผ๋ฏธํฐ
isFirstMission: Boolean?๋ ์ํ๋ช (shouldShowMissionStart)๊ณผ ์๋ฏธ๊ฐ ๋ค๋ฅด๊ณ nullable์ ๋๋ค. ๋์ผ ๋ช ์นญยท๋ถ๋ณ(Boolean)์ผ๋ก ์ ๋ฆฌํ๋ฉด ์ดํด์ ์ฌ์ฉ์ด ์ฌ์์ง๋๋ค.-private fun AlarmActionContent( +private fun AlarmActionContent( isAm: Boolean, hour: Int, minute: Int, todayDate: String, snoozeEnabled: Boolean, snoozeInterval: Int, snoozeCount: Int, - isFirstMission: Boolean?, + shouldShowMissionStart: Boolean, onSnoozeClick: () -> Unit, onDismissClick: () -> Unit, )ํธ์ถ๋ถ๋ ํจ๊ป:
- isFirstMission = state.shouldShowMissionStart, + shouldShowMissionStart = state.shouldShowMissionStart,
170-189: ๋ฒํผ ๋ ๋๋ง์ null ๊ฒ์ดํ ์ ๊ฑฐ๋ก UI ๋จ์ํ
initialLoadingํ๋ฉด์ด ์์ผ๋ฏ๋ก ์ฌ๊ธฐ์์null๋ถ๊ธฐ๋ ๋ถํ์ํฉ๋๋ค. ํญ์ ๋ฒํผ์ ๋ ๋๋งํ๊ณ ๋ผ๋ฒจ๋ง ๋ถ๊ธฐํ์ธ์.- if (isFirstMission != null) { - OrbitButton( - label = if (isFirstMission) { + OrbitButton( + label = if (shouldShowMissionStart) { stringResource(id = R.string.alarm_off_mission_start_btn) } else { stringResource(id = R.string.alarm_off_btn) - }, - enabled = true, - modifier = Modifier - .padding( - start = 40.dp, - end = 40.dp, - bottom = 48.dp, - ) - .height(62.dp), - onClick = onDismissClick, - ) - } else { - Spacer(modifier = Modifier.height(62.dp)) - } + }, + enabled = true, + modifier = Modifier + .padding(start = 40.dp, end = 40.dp, bottom = 48.dp) + .height(62.dp), + onClick = onDismissClick, + )
150-154: contentDescription ํ๋์ฝ๋ฉ โ stringResource๋ก i18n์ ๊ทผ์ฑ ๋ฌธ์์ด์ ๋ฆฌ์์ค๋ก ๋ถ๋ฆฌํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๋ฆฌ์์ค ์ถ๊ฐ ํ ๊ต์ฒด๋ฅผ ๊ถ์ฅํฉ๋๋ค.
์:
- contentDescription = "Alarm Action Character", + contentDescription = stringResource(id = R.string.alarm_action_character_cd),
208-213: "์ค์ /์คํ" ํ๋์ฝ๋ฉ ์ ๊ฑฐ๋ค๊ตญ์ด ๋์์ ์ํด ๋ฌธ์์ด ๋ฆฌํฐ๋ด ๋์ stringResource ์ฌ์ฉ์ ๊ถ์ฅํฉ๋๋ค.
์:
text = stringResource(if (isAm) R.string.am else R.string.pm)
299-313: ํ๋ฆฌ๋ทฐ ์ผ์ด์ค ๋ณด๊ฐ(๋ฏธ์ ์ ๋ฌด 2์ข )๋ฏธ์ ์์/์ผ๋ฐ ์ข ๋ฃ ๋ฒํผ ๋ผ๋ฒจ์ ๋ชจ๋ ๊ฒ์ฆํ ์ ์๋๋ก ํ๋ฆฌ๋ทฐ๋ฅผ 2๊ฐ๋ก ๋๋๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/action/AlarmActionViewModel.kt (3)
30-36: ์ด๊ธฐ Intent ์์ OK, ๋ค๋ง ์ด๊ธฐ๋ก๋ฉ ํด์ ํ์ด๋ฐ๋ง ์ผ๊ดํ ์ ์
fetchShouldShowMissionStart()โinitializeAlarmState()โstartClock()์์๋ ํฉ๋ฆฌ์ ์ ๋๋ค.initialLoading = false๋ ๋งค์ด๊ฐ ์๋๋ผ ์ฒซ ํฑ์์๋ง ๋ด๋ฆฌ๋๋ก ํ๋ฉด ๋ถํ์ํ ์ํ ๊ฐฑ์ ์ ์ค์ผ ์ ์์ต๋๋ค.
64-82: ๋ฌดํ ๋ฃจํ๋ ์ทจ์ ์นํ์ ์ผ๋ก์ทจ์ ์๊ทธ๋ ์ธ์ง ๋ช ํ์ฑ์ ์ํด
while (true)๋์coroutineContext.isActive์ฌ์ฉ์ ๊ถ์ฅํฉ๋๋ค.+import kotlinx.coroutines.isActive @@ - private fun startClock() = intent { - while (true) { + private fun startClock() = intent { + while (coroutineContext.isActive) { val now = LocalTime.now() ... delay(1000L) } }
84-98: Snooze ๋ค์ค ํญ ๊ฐ๋์ฐ์ ํญ ์ ์ฌ์ด๋์ดํํธ ์ค๋ณต ๋ด๋น๊ฒ์ด์ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค. ์ผ์์ ๋์ค์์ด๋ธ ํ๋๊ทธ๋ฅผ ์ํ์ ์ถ๊ฐํ๊ฑฐ๋, ์ฒ๋ฆฌ ์ค ๊ฐ๋๋ฅผ ๊ถ์ฅํฉ๋๋ค.
feature/home/src/main/AndroidManifest.xml (1)
3-3: ๊ถํ ์ค๋ณต ์ ์ธ ์ ๋ฆฌ ์ ์ACCESS_NETWORK_STATE๋ ๋ณดํต ์ฑ ๋ชจ๋ ๋งค๋ํ์คํธ์์๋ง ์ ์ธํฉ๋๋ค. ํผ์ฒ ๋ชจ๋ ์ ์ธ์ ๋ณํฉ ์ ์ค๋ณต์ด ๋๊ณ , ๋์ /์จ๋๋งจ๋ ๋ชจ๋์ธ ๊ฒฝ์ฐ ๋ถํ์ ๊ถํ ๋ ธ์ถ์ด ๋ ์ ์์ต๋๋ค. ์ฑ ๋งค๋ํ์คํธ์๋ง ์ ์งํ๊ณ ์ฌ๊ธฐ์๋ ์ ๊ฑฐํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
์ ์ฉ diff:
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> + <!-- moved to app/src/main/AndroidManifest.xml -->core/alarm/src/main/java/com/yapp/alarm/scheduler/PostFortuneTaskScheduler.kt (1)
3-5: ์ค์ผ์ค๋ง ๊ฐ์์ฑ ํฅ์์ ์ํ ๋ฐํ๊ฐ/๋ฌธ์ํ ์ ์ํธ์ถ ์ธก์์ โํ์ ์ฑ๊ณต/์คํตโ ์ฌ๋ถ๋ ํธ๋ํน ID๊ฐ ํ์ํ ์ ์์ต๋๋ค. Boolean(์ฑ๊ณต/์คํต) ๋ฐํ ๋๋ KDoc๋ก ๋์ ๋ณด์ฅ์ ๋ช ์ํ๋ ๊ฐ์ ์ ์ ์ํฉ๋๋ค.
์์ diff:
-interface PostFortuneTaskScheduler { - fun enqueueOnceForToday() -} +/** + * ์ค๋ ๋ ์ง ๊ธฐ์ค์ผ๋ก 1ํ๋ง ํ์ํฉ๋๋ค(์ค๋ณต ๋ฐฉ์ง). + * @return true๋ฉด ์๋ก ํ์๋จ, false๋ฉด ์ด๋ฏธ ํ์๋์ด ์คํต๋จ. + */ +interface PostFortuneTaskScheduler { + fun enqueueOnceForToday(): Boolean +}core/alarm/src/main/java/com/yapp/alarm/AndroidAlarmScheduler.kt (1)
20-27: ๋ก๊ทธ ์ค๋ฒํค๋ ์ ๊ฐ(์คํํธ๋ ์ด์ค/๋ฆด๋ฆฌ์ค ๋น๋ ์ฐจ๋จ)Throwable ์คํํธ๋ ์ด์ค๋ ๋น์ฉ์ด ํฝ๋๋ค. ๋๋ฒ๊ทธ/๋ก๊ฑฐ ๊ฐ๋๋ก ์ ํํ๊ณ ์คํํธ๋ ์ด์ค๋ ์ ๊ฑฐํ์ธ์.
๊ถ์ฅ diff:
- private fun logSchedule(tag: String, alarm: Alarm, triggerMillis: Long, extra: String = "") { - Log.d("ScheduleTrace", "scheduleAlarm Called", Throwable()) - Log.d( - "AlarmSchedule", - "[$tag] id=${alarm.id}, repeatDays=${alarm.repeatDays}, " + - "time=${java.time.Instant.ofEpochMilli(triggerMillis)} $extra", - ) - } + private fun logSchedule(tag: String, alarm: Alarm, triggerMillis: Long, extra: String = "") { + if (!BuildConfig.DEBUG && !Log.isLoggable("AlarmSchedule", Log.DEBUG)) return + Log.d( + "AlarmSchedule", + "[$tag] id=${alarm.id}, repeatDays=${alarm.repeatDays}, " + + "time=${java.time.Instant.ofEpochMilli(triggerMillis)} $extra" + ) + }core/ui/src/main/java/com/yapp/ui/component/navigation/NavigationBarScrim.kt (1)
16-26: ์ฌ์ฌ์ฉ์ฑ ๊ฐ์ : ์์/๋ชจ๋ํ์ด์ด ํ๋ผ๋ฏธํฐํ ์ ์ํ ๋ง ์คํฌ๋ฆผ ์ปฌ๋ฌ ์ฌ์ฉ์ด๋ zIndex ์กฐ์ ์ด ํ์ํ ์ ์์ด ํ๋ผ๋ฏธํฐํํ๋ฉด ํ์ฉ๋๊ฐ ์ฌ๋ผ๊ฐ๋๋ค.
์์ diff:
-@Composable -fun BoxScope.NavigationBarScrim() { - Box( - modifier = Modifier - .align(Alignment.BottomCenter) - .fillMaxWidth() - .windowInsetsBottomHeight(WindowInsets.navigationBars) - .background(Color.Black) - .zIndex(1f), - ) -} +@Composable +fun BoxScope.NavigationBarScrim( + modifier: Modifier = Modifier, + color: Color = Color.Black, + zIndex: Float = 1f, +) { + Box( + modifier = modifier + .align(Alignment.BottomCenter) + .fillMaxWidth() + .windowInsetsBottomHeight(WindowInsets.navigationBars) + .background(color) + .zIndex(zIndex), + ) +}feature/home/src/main/res/values/strings.xml (2)
51-53: '์ ํ๋จ' ๋ผ๋ฒจ์ ์ฌ์ฉ ๋งฅ๋ฝ์ a11y/UX ๊ด์ ์์ ํ์ธํด ์ฃผ์ธ์.ํ์ต ๋ฉ๋ชจ์(selectedMissionType/Count๋ ๋ด๋ถ ์ํ)๊ณผ ๊ฐ์ด '์ ํ๋จ'์ด ๊ฐ์ ํ ์คํธ๋ก ๋ ธ์ถ๋๋ฉด ์ ์ฅ/ํ์ ์ํ๋ก ์ค์ธ๋ ์ ์์ต๋๋ค. ์คํฌ๋ฆฐ๋ฆฌ๋์ฉ contentDescription๋ก๋ง ์ฐ์ด๊ฑฐ๋, UI์์๋ ์ฒดํฌ/์ ํ ์ํ๊ฐ ๋ช ํํ ์ ๋ฌ๋๋๋ก ํ์ธ ๋ถํ๋๋ฆฝ๋๋ค.
128-129: '๋ค์ ๋ณด์ง ์๊ธฐ' ๋์ ํ์ (์ฒดํฌ๋ฐ์ค vs ๋ฒํผ) ๋ช ํํ ๋ฐ ํ ์คํธ ์ผ๊ด์ฑ ํ์ธํด๋น ๋ฌธ์์ด์ด ํ ๊ธ(์ฒดํฌ๋ฐ์ค)์ธ์ง, 1ํ์ฑ ๋ฒํผ์ธ์ง์ ๋ฐ๋ผ ์ ๊ทผ์ฑ ๋ ์ด๋ธ/์ํ ์๋ด๊ฐ ๋ฌ๋ผ์ง๋๋ค. ์์ ฏ ํ์ ๊ณผ ์ผ์นํ๋๋ก ๋ณด์กฐ ํ ์คํธ(์: ์ค๋ช /์ ๊ทผ์ฑ ๋ ์ด๋ธ)๋ฅผ ์ถ๊ฐํ ์ง ๊ฒํ ํด ์ฃผ์ธ์.
app/src/main/java/com/yapp/orbit/di/AppVersionModule.kt (1)
11-18: @nAmed ๋์ ํ์ ์ธ์ดํํ @qualifier ์ฌ์ฉ ์ ์๋ฌธ์์ด Qualifier๋ ์ถฉ๋/์คํ ๋ฆฌ์คํฌ๊ฐ ์์ต๋๋ค. ์ ์ฉ @qualifier๋ฅผ ๋์ ํด ํ์ ์ธ์ดํํ๊ฒ ๊ด๋ฆฌํด ์ฃผ์ธ์.
package com.yapp.orbit.di @@ import dagger.hilt.components.SingletonComponent -import javax.inject.Named import javax.inject.Singleton +import javax.inject.Qualifier @@ -@Module -@InstallIn(SingletonComponent::class) -object AppVersionModule { +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class AppVersion + +@Module +@InstallIn(SingletonComponent::class) +object AppVersionModule { @Provides @Singleton - @Named("appVersion") - fun provideAppVersion(): String = BuildConfig.VERSION_NAME + @AppVersion + fun provideAppVersion(): String = BuildConfig.VERSION_NAME }core/designsystem/src/main/res/raw/fortune_loading.json (1)
1-1: Lottie ์๋ณธ ๋ผ์ด์ ์ค/ํฌ๊ธฐ ๊ฒ์ฆ ํ์
- ๋์ฉ๋ base64 WebP ์์ ์ธ๋ผ์ธ์ APK/๋ฉ๋ชจ๋ฆฌ ํํ๋ฆฐํธ๋ฅผ ๋๋ฆฝ๋๋ค. ๊ฐ๋ฅํ๋ฉด ๋ฒกํฐํ/์์ ๋ถ๋ฆฌ/์์ถ์ ๊ฒํ ํ์ธ์.
- ์๋ณธ ๋ผ์ด์ ์ค(์์ ์ ์ด์ฉ/๋ณ๊ฒฝ ํ์ฉ ์ฌ๋ถ)์ ๊ท์ ํ๊ธฐ๋ฅผ ํ์ธํด ์ฃผ์ธ์.
domain/src/main/java/com/yapp/domain/model/AlarmDay.kt (1)
16-23: ์๋ฐฉํฅ ๋งคํ ๋ก์ง์ ๋ง์ต๋๋ค๋ง, enum ์์ ์์กด์ฑ ์ ๊ฑฐ ๊ถ์ฅํ์ฌ ๊ตฌํ์ entries/ordinal์ ์์กดํฉ๋๋ค. enum ์์ ๋ณ๊ฒฝ์ ์ทจ์ฝํ๋ฏ๋ก ๋ช ์์ ๋งคํ์ผ๋ก ๋ฐ๊พธ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
-fun AlarmDay.toDayOfWeek(): DayOfWeek { - return DayOfWeek.of(((this.ordinal + 6) % 7) + 1) -} +fun AlarmDay.toDayOfWeek(): DayOfWeek = when (this) { + AlarmDay.SUN -> DayOfWeek.SUNDAY + AlarmDay.MON -> DayOfWeek.MONDAY + AlarmDay.TUE -> DayOfWeek.TUESDAY + AlarmDay.WED -> DayOfWeek.WEDNESDAY + AlarmDay.THU -> DayOfWeek.THURSDAY + AlarmDay.FRI -> DayOfWeek.FRIDAY + AlarmDay.SAT -> DayOfWeek.SATURDAY +} -fun DayOfWeek.toAlarmDay(): AlarmDay { - val index = (this.value % 7) - return AlarmDay.entries[index] -} +fun DayOfWeek.toAlarmDay(): AlarmDay = when (this) { + DayOfWeek.SUNDAY -> AlarmDay.SUN + DayOfWeek.MONDAY -> AlarmDay.MON + DayOfWeek.TUESDAY -> AlarmDay.TUE + DayOfWeek.WEDNESDAY -> AlarmDay.WED + DayOfWeek.THURSDAY -> AlarmDay.THU + DayOfWeek.FRIDAY -> AlarmDay.FRI + DayOfWeek.SATURDAY -> AlarmDay.SAT +}data/src/main/java/com/yapp/data/local/datasource/UserLocalDataSource.kt (1)
9-10: Epoch ๋จ์/ํ์์กด ๋ช ์ธ ํ์
- updateNoticeLastShownDateEpochFlow์ ๋จ์(์ด/๋ฐ๋ฆฌ์ด)์ ๊ธฐ์ค(UTC/local midnight) ๋ช ์๊ฐ ํ์ํฉ๋๋ค. ๋ ์ง ๋น๊ต ๋ก์ง๊ณผ ๋ถ์ผ์น ์ ์ค๋์ํ ์ ์์ต๋๋ค.
- markUpdateNoticeShownToday๊ฐ ์ด๋ค ๊ธฐ์ค ์๊ฐ์ ์ ์ฅํ๋์ง KDoc์ ๋ช ํํ ๋จ๊ฒจ ์ฃผ์ธ์.
Also applies to: 15-16
app/src/main/java/com/yapp/orbit/OrbitApplication.kt (1)
11-11: ๋น ๊ธฐ๋ณธ ์์ฑ์ ์ ๊ฑฐ ๊ฐ๋ฅstatic analysis ๋๊ตฌ๊ฐ ์ง์ ํ ๊ฒ์ฒ๋ผ ๋น ๊ธฐ๋ณธ ์์ฑ์
()๋ ์ ๊ฑฐํ ์ ์์ต๋๋ค.-class OrbitApplication() : Application(), Configuration.Provider { +class OrbitApplication : Application(), Configuration.Provider {app/src/main/AndroidManifest.xml (1)
5-5: ACCESS_NETWORK_STATE ๊ถํ ์ค๋ณต ์ ์ธ
android.permission.ACCESS_NETWORK_STATE๊ถํ์ด 5๋ฒ๊ณผ 14๋ฒ ๋ผ์ธ์ ์ค๋ณต ์ ์ธ๋์ด ์์ต๋๋ค.14๋ฒ ๋ผ์ธ์ ์ค๋ณต๋ ๊ถํ ์ ์ธ์ ์ ๊ฑฐํ์ธ์:
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>Also applies to: 14-14
core/alarm/src/main/java/com/yapp/alarm/receivers/AlarmReceiver.kt (1)
114-119: ๋ก์ปฌ ํจ์ ์ ์ธ ์์น ๊ฐ์ ํ์
ringsToday()ํจ์๊ฐ ์ฝ๋ฃจํด ์ค์ฝํ ๋ด๋ถ์ ์ ์ธ๋์ด ์์ต๋๋ค. ์ด ํจ์๋ ์ํ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ์์ ํจ์์ด๋ฏ๋ก ํด๋์ค ๋ ๋ฒจ์ด๋ ์๋จ์ ์ ์ธํ๋ ๊ฒ์ด ๋ ์ ์ ํฉ๋๋ค.ํจ์๋ฅผ ํด๋์ค์ private ๋ฉ์๋๋ก ์ด๋ํ๊ฑฐ๋ companion object์ ์ถ๊ฐํ์ธ์:
- fun Alarm.ringsToday(): Boolean { - if (repeatDays == 0) return true - - val todayAlarmDay = LocalDate.now().dayOfWeek.toAlarmDay() - return (repeatDays and todayAlarmDay.bitValue) != 0 - }ํด๋์ค ๋ ๋ฒจ์ ์ถ๊ฐ:
private fun Alarm.ringsToday(): Boolean { if (repeatDays == 0) return true val todayAlarmDay = LocalDate.now().dayOfWeek.toAlarmDay() return (repeatDays and todayAlarmDay.bitValue) != 0 }domain/src/main/java/com/yapp/domain/repository/FortuneRepository.kt (2)
20-20: ์ด๋ฆ ๋ถ์ผ์น ๊ฐ๋ฅ์ฑ: markFortuneAsFailed vs markFortuneFaileddatastore(UserPreferences) ์ชฝ ๊ตฌํ์ markFortuneFailed๋ก ๋ณด์ ๋๋ค. ๋ ์ด์ด ๊ฐ ๋ช ๋ช ํต์ผ์ ๊ถ์ฅํฉ๋๋ค. ๋๋ฉ์ธ ๋ฉ์๋๋ฅผ markFortuneFailed๋ก ๋ง์ถ๊ฑฐ๋ ๋ฐ์ดํฐ ๊ณ์ธต์ AsFailed๋ก ๋ง์ถฐ ์ฃผ์ธ์.
- suspend fun markFortuneAsFailed() + suspend fun markFortuneFailed()
9-16: ํ์ธ ์๋ฃ โ ๋๋ฉ์ธ API ๋ณ๊ฒฝ์ด ์ ํ๋จ; KDoc ๋ง์ด๊ทธ๋ ์ด์ ๊ฐ์ด๋ ์ถ๊ฐ ๊ถ์ฅ๊ฒ์ฆ ๊ฒฐ๊ณผ: ์ด์ ์ฌ๋ณผ(fortuneDateFlow ๋ฑ)์ ์ฝ๋๋ฒ ์ด์ค์์ ๋ฐ๊ฒฌ๋์ง ์์๊ณ , ์ ์ฌ๋ณผ(fortuneDateEpochFlow, hasUnseenFortuneFlow, shouldShowFortuneToolTipFlow, isFirstAlarmDismissedTodayFlow, fortuneCreateStatusFlow)์ด domain/data/feature ๋ชจ๋ ์ ์ญ์์ ์ฌ์ฉ๋๊ณ ์์ต๋๋ค.
ํ์ธ ํ์ผ(์): 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/UserPreferences.kt, feature/* (Home/Mission/Fortune/Alarm).
์กฐ์น: ๊ฐ Flow์ ์๋ฏธ(ํ๋ฃจ/epoch ๊ธฐ์ค, reset ์กฐ๊ฑด)์ mark* ๊ณ์ด ๋ฉ์๋์ ์ํ ์ ์ด๋ฅผ ๊ฐ๋จํ KDoc์ผ๋ก ๋ฌธ์ํํ์ธ์.core/datastore/src/main/java/com/yapp/datastore/UserPreferences.kt (2)
44-45: todayEpoch ํ ์คํธ ๊ฐ๋ฅ์ฑ/๊ฒฐ์ ์ฑ ๊ฐ์ ์ ์๋ก์ปฌ ์๊ฐ๋/์์ ๊ฒฝ๊ณ ์ด์ ํ ์คํธ๋ฅผ ์ํด Clock ์ฃผ์ (๋๋ provider ํจ์ ์ฃผ์ )์ ๊ถ์ฅํฉ๋๋ค.
์: ์์ฑ์์ Clock ์ฃผ์ ํ
LocalDate.now(clock).toEpochDay()์ฌ์ฉ.
108-116: FIRST_ALARM_DISMISSED_TODAY ํ๋๊ทธ ์ ๋ฆฌ(์ต์ )ํ๋ก์ฐ์์ ๋ ์ง ๋น๊ต๋ก ์์ ํ์ง๋ง, ๋ฐ์ดํฐ ์ฒญ๊ฒฐ์ ์ํด ๋ ์ง๊ฐ ๋ฐ๋๋ฉด ํ๋๊ทธ๋ฅผ false๋ก ์ฌ์ค์ ํ๋ ์ ์ง๋ณด์์ฉ ์ ๋ฆฌ ๋ก์ง์ ๊ณ ๋ คํด๋ณผ ์ ์์ต๋๋ค.
feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/AlarmInteractionActivity.kt (1)
52-65: ๋ค๋น๊ฒ์ด์ ๋ฐ ํจ๋ฉ + ์คํฌ๋ฆผ ์กฐํฉ ์ฌ์ฉ ์ ์ด์ค ํจ๋ฉ ์ฌ๋ถ ํ์ธ ์์ฒญNavHost์ navigationBarsPadding์ ์ฃผ๊ณ ๋ฐ๋ฅ์ ์คํฌ๋ฆผ์ ๊น์์ผ๋ ๋๋ถ๋ถ OK์ ๋๋ค. ๋ค๋ง ๋ด๋ถ ํ๋ฉด๋ค์ด ๋ณ๋๋ก navigationBarsPadding/WindowInsets๋ฅผ ์ฒ๋ฆฌํ๊ณ ์๋ค๋ฉด ํ๋จ ์ฌ๋ฐฑ์ด ๊ณผ๋คํด์ง ์ ์์ด ์ค์ ๋จ๋ง(์ ์ค์ฒ/3๋ฒํผ ๋ด๋น ๋ชจ๋)์์ ํ์ธ ๋ถํ๋๋ฆฝ๋๋ค. ๋ํ Box์ ํฌ๊ธฐ ์ ์ฝ์ด ๋ชจํธํ ๊ฒฝ์ฐ๋ฅผ ๋ง์ผ๋ ค๋ฉด fillMaxSize๋ฅผ ๋ถ์ฌํ๋ ๊ฒ๋ ๊ณ ๋ คํด ์ฃผ์ธ์.
core/common/src/main/java/com/yapp/common/navigation/route/MissionRoute.kt (1)
8-11: ๋ฌธ์์ด ๋์ ํ์ ์ธ์ดํ enum ์ฌ์ฉ ๊ณ ๋ ค
missionMode: String๋์MissionMode์์ฒด๋ฅผ ์ฌ์ฉํ๋ฉด ์คํ/์คํ ๋ถ์ผ์น๋ฅผ ์ปดํ์ผ ํ์์ ์ฐจ๋จํ ์ ์์ต๋๋ค(ํ์ ์ @serializable enum). ๋ค๋น๊ฒ์ด์ ์ธ์ฝ๋ฉ/๋์ฝ๋ฉ ์ํฅ ๋ฒ์๋ฅผ ๊ฐ์ํด ํ์ ๋ฆฌํฉํฐ๋ก ๊ฒํ ํด ์ฃผ์ธ์.feature/fortune/src/main/java/com/yapp/fortune/page/FortunePager.kt (1)
43-61: ํ์ด์ง ์ธ๋ฑ์ค ๋งค์ง๋๋ฒ ์ ๋ฆฌ ์ ์
in 1..4,5 ->๋ฑ ํ๋์ฝ๋ฉ๋ ์ธ๋ฑ์ค๋ ์ ์ง๋ณด์ ์ ์ค๋ฅ๋ฅผ ์ ๋ฐํฉ๋๋ค. ์์/ํ์ ๊ฐ์ผ๋ก ์ค์์ง์คํํ๊ฑฐ๋ state ๊ธฐ๋ฐ์ผ๋ก ๊ณ์ฐํ๋๋ก ์ ๋ฆฌํด ์ฃผ์ธ์.feature/fortune/src/main/java/com/yapp/fortune/FortuneNavGraph.kt (1)
23-27: ๋ฅ๋งํฌ URI ํจํด ์์ํ
"orbitapp://fortune"๋ฌธ์์ด์ ์์๋ก ๋ถ๋ฆฌํด ์ฌ์ฌ์ฉํ๋ฉด ์คํ์/์ค๋ณต ๊ด๋ฆฌ๊ฐ ์์ํฉ๋๋ค.feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/snooze/AlarmSnoozeTimerViewModel.kt (1)
47-49: Clock ์ฃผ์ ์ผ๋ก ํ ์คํธ ์ฉ์ด์ฑ/์ผ๊ด์ฑ ํฅ์ ์ ์
LocalDate.now()๋์Clock์ DI ๋ฐ์LocalDate.now(clock)์ ์ฐ๋ฉด ์คํ๋ผ์ธ/ํ์์กด/ํ ์คํธ ์๋๋ฆฌ์ค์์ ์์ ์ ์ ๋๋ค.// ์์ class AlarmSnoozeTimerViewModel @Inject constructor( private val clock: Clock, ... ) : ViewModel(), ... { ... val todayDate = LocalDate.now(clock).toEpochDay() }feature/fortune/src/main/java/com/yapp/fortune/scheduler/WorkManagerPostFortuneTaskScheduler.kt (1)
21-31: ์ผ์ผ ๊ณ ์ ์ํฌ ์ด๋ฆ ์ ๋ต OK โ ํ๊ทธ/๋ชจ๋ํฐ๋ง ์ถ๊ฐ ๊ถ์ฅ์ ๋ํฌ ๋ค์ด๋ฐ+KEEP ์ ์ฑ ์ ์๋์ ๋ถํฉํฉ๋๋ค. ์ด์ ๋ชจ๋ํฐ๋ง์ ์ํด ํ๊ทธ๋ฅผ ์ถ๊ฐํ๊ณ , ์คํจ/์ฌ์๋ ์ถ์ ์ด ํ์ํ๋ฉด ๋ก๊ทธ/๋ถ์ ์ด๋ฒคํธ๋ฅผ Worker์์ ๋ฐํํ์ธ์.
val req = OneTimeWorkRequestBuilder<PostFortuneWorker>() .setConstraints(constraints) - .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 15, TimeUnit.SECONDS) + .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 15, TimeUnit.SECONDS) + .addTag(POST_FORTUNE_TAG) .build()// ํ์ผ ํ๋จ ๋ฑ private const val POST_FORTUNE_TAG = "post_fortune"๋ํ,
PostFortuneWorker๊ฐ@HiltWorker๋ก ์ ์ธ๋๊ณHiltWorkerFactory๊ฐ Application์ ์ฐ๊ฒฐ๋์ด ์๋์ง ํ์ธํด ์ฃผ์ธ์.domain/src/main/java/com/yapp/domain/repository/UserInfoRepository.kt (1)
11-12: ์ด๋ฆ ๋ช ํ์ฑ: Epoch โ EpochDay ๊ถ์ฅ
updateNoticeLastShownDateEpochFlow๋ ๋ฐ๋ฆฌ์ด epoch๋ก ์คํด๋ ์ ์์ต๋๋ค. ์ผ ๋จ์๋ผ๋ฉด...EpochDayFlow์ ๊ฐ์ด ๋ช ํํ ํ๋ ๊ฒ์ ๊ณ ๋ คํด ์ฃผ์ธ์(๋๋ฉ์ธ ์ ๋ฐ ๋์ ์ ๋ฆฌ ์ ์ ).feature/fortune/src/main/java/com/yapp/fortune/FortuneScreen.kt (4)
220-224: LottieAnimation์ width๊ฐ ๋ฌด์๋ฉ๋๋ค (๋ด๋ถ์์ fillMaxWidth ๊ณ ์ ).ํ์ฌ LottieAnimation ์ปดํฌ์ ๋ธ์ด ๋ด๋ถ์ ์ผ๋ก
modifier.fillMaxWidth()๋ฅผ ๊ฐ์ ํ๋ฏ๋ก, ํธ์ถ๋ถ์.width(375.dp)๋ ํจ๊ณผ๊ฐ ์์ต๋๋ค. ์๋๋๋ก ๊ฐ๋ก/์ธ๋ก ๋น์จ์ ๋ง์ถ๋ ค๋ฉดaspectRatio๋ก ์ ์ดํ๊ฑฐ๋ width๋ฅผ ์ ๊ฑฐํ์ธ์.์๋์ฒ๋ผ ์์ ๊ถ์ฅ:
- LottieAnimation( - modifier = Modifier - .width(375.dp) - .height(267.dp), - resId = core.designsystem.R.raw.fortune_loading, - ) + LottieAnimation( + modifier = Modifier + .fillMaxWidth() + .aspectRatio(375f / 267f), + resId = core.designsystem.R.raw.fortune_loading, + )์ถ๊ฐ import:
+import androidx.compose.foundation.layout.aspectRatio
174-181: ์ฌ๋ผ์ด๋ฉ ์ธ๋์ผ์ดํฐ count ํ๋์ฝ๋ฉ(6) โ ์ค์ ํ์ด์ง ์์ ๋๊ธฐํ ํ์.
rememberPagerState(pageCount = { state.fortunePages.size + 2 })์ ๋ถ์ผ์น ์ ์งํ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฉ๋๋ค. ๋์ผ ๊ณ์ฐ์ ๋๋pagerState.pageCount๋ก ์นํํ์ธ์.- SlidingIndicator( - currentIndex = pagerState.currentPage, - count = 6, + SlidingIndicator( + currentIndex = pagerState.currentPage, + count = pagerState.pageCount, // ๋์: state.fortunePages.size + 2
PagerState.pageCount๊ฐ์ฉ ์ฌ๋ถ ํ์ธ ๋ถํ๋๋ฆฝ๋๋ค. ๋ถ๊ฐํ๋ฉด ๋์ผ ๋๋ค ๊ณ์ฐ์์ ์ฌ์ฉํ์ธ์.
83-91: ๋น ์ด๋ฒคํธ ํ์ ("") ๋ก๊น ๋ฐฉ์ง.
else -> ""๋ก ์ค์ ๋ ๊ฒฝ์ฐ์๋ ๋ก๊ทธ๋ฅผ ์์ต๋๋ค. ๊ณต๋ฐฑ์ธ ๊ฒฝ์ฐ ๋ก๊น ์ ์คํตํ์ธ์.- analyticsHelper.logEvent( - AnalyticsEvent( - type = eventType, - properties = mapOf( - AnalyticsEvent.FortunePropertiesKeys.FORTUNE_PAGE_NUMBER to pagerState.currentPage + 1, - ), - ), - ) + if (eventType.isNotBlank()) { + analyticsHelper.logEvent( + AnalyticsEvent( + type = eventType, + properties = mapOf( + AnalyticsEvent.FortunePropertiesKeys.FORTUNE_PAGE_NUMBER to pagerState.currentPage + 1, + ), + ), + ) + }
191-199: ๋ฌดํ ๋ฃจํ LaunchedEffect ๋จ์ํ ๊ฐ๋ฅ.
while(true) + delay๋์rememberInfiniteTransition๋ฑ ์ ๋๋ฉ์ด์ API๋ก ํ ๊ธํ๋ฉด ๊ฐ๋ ์ฑ๊ณผ ์ทจ์ ์ฒ๋ฆฌ ๋ชจ๋ ๊ฐ์ ๋ฉ๋๋ค. ๊ธฐ๋ฅ์ ๋์ผํ๋ฏ๋ก ์ ํ์ฌํญ์ ๋๋ค.val transition = rememberInfiniteTransition(label = "deliverToggle") val phase by transition.animateFloat( initialValue = 0f, targetValue = 1f, animationSpec = infiniteRepeatable(animation = tween(2000), repeatMode = RepeatMode.Reverse), label = "phase" ) val isDelivering = phase > 0.5fdata/src/main/java/com/yapp/data/repositoryimpl/UserInfoRepositoryImpl.kt (1)
20-21: Epoch ๋จ์ ๋ช ์ ํ์(์ด vs ๋ฐ๋ฆฌ์ด).
updateNoticeLastShownDateEpochFlow: Flow<Long?>์ ๋จ์๊ฐ ๋ถ๋ช ํํฉ๋๋ค. ์ธํฐํ์ด์ค/๋๋ฉ์ธ ์ ๋ฐ์์epochMillis๋ฑ์ผ๋ก ์ด๋ฆ์ ๋ช ์ํ๊ฑฐ๋ KDoc์ ๋จ์๋ฅผ ๊ณ ์ ํด ์ฃผ์ธ์.data/src/main/java/com/yapp/data/local/datasource/UserLocalDataSourceImpl.kt (1)
14-15: Epoch ๋จ์ ๋ช ์ ํ์(์ด vs ๋ฐ๋ฆฌ์ด).
updateNoticeLastShownDateEpochFlow์ ๋จ์๋ฅผ ์ธํฐํ์ด์ค์ ์ผ๊ด๋๊ฒ ๋ฌธ์ํ/๋ช ๋ช ํด ์ฃผ์ธ์. ์์ ๋ ์ด์ด์ ๋์ผ ์ ์ ์ ์ฉ ๊ถ์ฅ.feature/fortune/src/main/java/com/yapp/fortune/FortuneViewModel.kt (2)
53-72: ์ค๋ณต Success ๋ฐฉ์ง: ๋์ผ ์ํ ์ฌ๋ฐฉ์ถ ์ ์ค๋ณต fetch ๊ฐ๋ฅ.
collect๋ ๋์ผSuccess์ฌ๋ฐฉ์ถ์๋fetchAndUpdateFortune๋ฅผ ๋ค์ ํธ์ถํ ์ ์์ต๋๋ค.distinctUntilChanged/collectLatest๋ก ๋๋ฐ์ด์คํ์ธ์.-import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.distinctUntilChanged @@ - private fun observeFortune() = intent { - fortuneRepository.fortuneCreateStatusFlow.collect { status -> + private fun observeFortune() = intent { + fortuneRepository.fortuneCreateStatusFlow + .distinctUntilChanged() + .collectLatest { status ->
99-103: ๋คํธ์ํฌ ์คํจ ์ UX ๋์ ํ์.
getFortune์คํจ ์ ๋ก๋ฉ๋ง ํด์ ๋๊ณ ํ๋ฉด์ด ์ ์ง ์ํ๊ฐ ๋ ์ ์์ต๋๋ค. ํ ์ด๋ ๋๋ ์ฌ์๋/์๋ฆผ ํ ์คํธ ์ค ํ๋๋ก ์ฒ๋ฆฌํ์ธ์.}.onFailure { error -> Log.e("FortuneViewModel", "์ด์ธ ๋ฐ์ดํฐ ์์ฒญ ์คํจ: ${error.message}") reduce { state.copy(isLoading = false) } + postSideEffect(FortuneContract.SideEffect.NavigateToHome) }core/alarm/src/main/java/com/yapp/alarm/receivers/AlarmInteractionActivityReceiver.kt (2)
49-53: Broadcast ์๊ฐ ์ ํ ๋๋น: Flow first()์ ํ์์์ ๊ถ์ฅ.๋ธ๋ก๋์บ์คํธ ์ปจํ ์คํธ์์๋ ์ง์ฐ์ด ๊ธธ์ด์ง๋ฉด OS๊ฐ ์ค๋จํ ์ ์์ต๋๋ค.
withTimeout์ผ๋ก ์์ ์ฅ์น ์ถ๊ฐ๋ฅผ ๊ถ์ฅํฉ๋๋ค.-import kotlinx.coroutines.withContext +import kotlinx.coroutines.withContext +import kotlinx.coroutines.withTimeout @@ - val (fortuneCreateStatus, hasUnseenFortune) = withContext(Dispatchers.IO) { - val status = fortuneRepository.fortuneCreateStatusFlow.first() - val unseen = fortuneRepository.hasUnseenFortuneFlow.first() - status to unseen - } + val (fortuneCreateStatus, hasUnseenFortune) = withContext(Dispatchers.IO) { + withTimeout(3_000) { + val status = fortuneRepository.fortuneCreateStatusFlow.first() + val unseen = fortuneRepository.hasUnseenFortuneFlow.first() + status to unseen + } + }
81-82: Failure/Idle ๋ถ๊ธฐ ์ฒ๋ฆฌ ๋ช ์์ ์.์๋ฌด ๋์ ์์์ด ์๋๋ผ๋ฉด OK์ ๋๋ค. ํ์ ์ ๋ก๊น /ํธ๋ ์ด์ฑ๋ง ์ถ๊ฐ ๊ฒํ .
feature/fortune/src/main/java/com/yapp/fortune/worker/PostFortuneWorker.kt (1)
49-55: ์ฌ์๋ ๊ธฐ์ค์ ๊ตฌ๋ถ(์ฌ์๋ ๊ฐ๋ฅ/๋ถ๊ฐ)ํ์ธ์.์๋ฒ 4xx ๋ฑ ์๊ตฌ ์คํจ์์๋ Result.retry()๋ฅผ ๋ฐํํ๋ฉด ๋ฐฑ์คํ ์ฌ์๋๊ฐ ๋ถํ์ํ๊ฒ ๊ณ์๋ ์ ์์ต๋๋ค. ์ ์ฅ์/๋๋ฉ์ธ ์๋ฌ ํ์ ์ ๊ตฌ๋ถํด ์ฌ์๋ ๋ถ๊ฐ์ธ ๊ฒฝ์ฐ Result.failure()๋ฅผ ๋ฐํํ๋ ๋ถ๊ธฐ๋ฅผ ์ถ๊ฐํด ์ฃผ์ธ์.
- onFailure = { - fortuneRepository.markFortuneAsFailed() - // WM ๋ฐฑ์คํ ๊ท์น์ ๋ฐ๋ผ ์ฌ์๋ - Result.retry() - }, + onFailure = { e -> + fortuneRepository.markFortuneAsFailed() + // ์: ๋๋ฉ์ธ ์์ธ/HTTP ์ํ์ ๋ฐ๋ผ ์ฌ์๋ ์ฌ๋ถ ๊ฒฐ์ + if (e is TransientNetworkException /* or 5xx */) { + Result.retry() + } else { + Result.failure() + } + },feature/home/src/main/java/com/yapp/home/component/bottomsheet/UpdateNoticeBottomSheet.kt (3)
110-115: ์ก์ ์์ญ์ ์ ๊ทผ์ฑ Role ๋ถ์ฌ.๋ฒํผ ์ญํ ์ ๋ช ์ํด ์คํฌ๋ฆฐ๋ฆฌ๋ ํ์ ํ์ง์ ๋์ฌ์ฃผ์ธ์.
- Box( + Box( modifier = Modifier .weight(1f) - .clickable(onClick = onDontShowAgain) + .clickable(role = androidx.compose.ui.semantics.Role.Button, onClick = onDontShowAgain) .padding(vertical = 14.dp), contentAlignment = Alignment.Center, ) { @@ - Box( + Box( modifier = Modifier .weight(1f) - .clickable(onClick = onClose) + .clickable(role = androidx.compose.ui.semantics.Role.Button, onClick = onClose) .padding(vertical = 14.dp), contentAlignment = Alignment.Center, ) {Also applies to: 124-128
64-70: ์คํฌ๋ฆผ ํด๋ฆญ์ Ripple ์ ๊ฑฐ ๋ฐ ๋ผ๋ฒจ ๋ถ์ฌ.์ ์ฒด ์คํฌ๋ฆผ ํด๋ฆญ์ ๋ฌผ๊ฒฐ ํจ๊ณผ๊ฐ ๋ถํ์ํ๋ฉฐ, ์คํฌ๋ฆฐ๋ฆฌ๋ ๋ผ๋ฒจ์ ๋ถ์ฌํ๋ฉด ๋ ๋ซ์ต๋๋ค.
- Box( + Box( modifier = Modifier .fillMaxSize() - .background(Color(0xFF17191F).copy(alpha = 0.85f)) - .clickable(onClick = onClose), + .background(Color(0xFF17191F).copy(alpha = 0.85f)) + .clickable( + onClickLabel = stringResource(id = R.string.update_notice_bottom_sheet_close), + indication = null, + interactionSource = remember { MutableInteractionSource() }, + onClick = onClose, + ), contentAlignment = Alignment.BottomCenter, ) {
93-101: ๋ฐฐ๋ ์ด๋ฏธ์ง ๋ก๋ฉ crossfade ์ถ๊ฐ๋ก ์ ํ ํ์ง ๊ฐ์ .๋คํธ์ํฌ ๋ก๋ฉ์ ๊น๋นก์์ ์ค์ ๋๋ค.
+import coil.request.ImageRequest @@ - AsyncImage( - model = imageUrl, + AsyncImage( + model = ImageRequest.Builder(context) + .data(imageUrl) + .crossfade(true) + .build(), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier .fillMaxWidth() .aspectRatio(1f), )feature/mission/src/main/java/com/yapp/mission/MissionViewModel.kt (1)
142-149: ๋ Flow๋ฅผ ์ผ๊ด๋ ์ค๋ ์ท์ผ๋ก ์ฝ์ด ์กฐ๊ฑด ํ์ ํ์ธ์.์๋ก ๋ค๋ฅธ ์์ ์ first() ๊ฒฐ๊ณผ ์กฐํฉ์ผ๋ก ๊ฒฝ๊ณ ํ์ด๋ฐ์์ ์๋ชป๋ ํ๋จ์ด ๊ฐ๋ฅ. combine์ผ๋ก ์ค๋ ์ท์ ๋ง๋ ๋ค first()๋ฅผ ๊ถ์ฅํฉ๋๋ค.
- val fortuneCreateStatus = fortuneRepository.fortuneCreateStatusFlow.first() - val hasUnseenFortune = fortuneRepository.hasUnseenFortuneFlow.first() + val (fortuneCreateStatus, hasUnseenFortune) = + kotlinx.coroutines.flow.combine( + fortuneRepository.fortuneCreateStatusFlow, + fortuneRepository.hasUnseenFortuneFlow, + ) { a, b -> a to b }.first()core/alarm/src/main/java/com/yapp/alarm/services/AlarmService.kt (2)
112-115: Notification ID์ Int ๋ณํ ์์ ํ.Long โ Int ์บ์คํ ์ overflow ์ํ์ด ์์ต๋๋ค. ํญ์ ์์ 32๋นํธ ๋ฒ์๋ก ๋งคํํ์ธ์.
- startForeground( - notificationId.toInt(), - createNotification(alarm, shouldNavigateToMission(alarm.missionType)), - ) + val notificationIdInt = (notificationId % Int.MAX_VALUE).toInt() + startForeground( + notificationIdInt, + createNotification(alarm, shouldNavigateToMission(alarm.missionType)), + )
199-206: ์๋น์ค ์๋ช ์ฃผ๊ธฐ ์ค์ฝํ๋ก ํต์ผ.๋ณ๋ CoroutineScope ๋์ serviceScope๋ฅผ ์ฌ์ฉํด ์ทจ์ยท์ข ๋ฃ ์ ์ผ๊ด๋๊ฒ ์ ๋ฆฌ๋๋๋ก ํฉ๋๋ค.
- CoroutineScope(Dispatchers.IO).launch { + serviceScope.launch { alarmUseCase.updateAlarmActive( id = alarmId, active = false, ) }feature/home/src/main/java/com/yapp/home/HomeViewModel.kt (1)
457-464: ๋คํธ์ํฌ ํ์ ์ํ/์ฃผ์ ํ Clock ๊ณ ๋ ค.
- VALIDATED ๋ฏธ์ถฉ์กฑ(ํฌํธ/์ด๊ธฐ ์ฐ๊ฒฐ)์์๋ ํ์๋ฅผ ๋ง์ ์ ์์ต๋๋ค. INTERNET๋ง ๋ง์กฑ ์ ์ผ๋จ ํ์ํ๋๋ก ์ํํ๊ฑฐ๋, ์ต์ ์ง์ฐ ํ ์ฌํ๊ฐ๋ฅผ ๊ณ ๋ คํ์ธ์.
- LocalDate.now() ๊ธฐ๋ฐ ๋ก์ง์ด ๋ง์ผ๋ฏ๋ก ํ ์คํธ ์ฉ์ด์ฑ๊ณผ ๊ฒฝ๊ณ ์์ (์์ ) ์ ์ด๋ฅผ ์ํด Clock ์ฃผ์ ๋ ๊ณ ๋ คํด ๋ณผ ๋งํฉ๋๋ค.
data/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSource.kt (2)
8-8: epoch ๋จ์ ๋ช ํํ ํด์ฃผ์ธ์.
fortuneDateEpochFlow๊ฐ epoch day(Long, toEpochDay) ๊ธฐ๋ฐ์ด๋ฉด ์ด๋ฆ์fortuneDateEpochDayFlow๋ฑ์ผ๋ก ๋ ๊ตฌ์ฒดํํ๊ฑฐ๋ KDoc์ผ๋ก โepoch milliseconds๊ฐ ์๋โ์ ๋ช ์ํด ์ฃผ์ธ์. ํผ๋์ผ๋ก ์ธํ ๋ฒ๊ทธ๋ฅผ ์ค์ผ ์ ์์ต๋๋ค.
12-12: Tooltip ๋ค์ด๋ฐ ์ผ๊ด์ฑ ๊นจ์ง(โToolTipโ vs โTooltipโ).
shouldShowFortuneToolTipFlow์markFortuneTooltipShown()์ ํ๊ธฐ๊ฐ ๋ค๋ฆ ๋๋ค. ์ผ๊ด๋๊ฒTooltip๋ก ๋ง์ถฐ ์ฃผ์ธ์.์ ์ฉ ์(์ธํฐํ์ด์ค ๊ธฐ์ค):
- val shouldShowFortuneToolTipFlow: Flow<Boolean> + val shouldShowFortuneTooltipFlow: Flow<Boolean>Also applies to: 21-21
feature/home/src/main/java/com/yapp/home/HomeScreen.kt (4)
416-422: API ๋ ๋ฒจ ๋ถ๊ธฐ ๋์ ์์ ์์ญ(WindowInsets.safeDrawing) ์ฌ์ฉ ๊ถ์ฅ.SDK 35 ๋ถ๊ธฐ๋ ์ ์ง๋ณด์ ๋น์ฉ์ด ํฌ๊ณ ๊ธฐ๊ธฐ๋ณ/์ ์กฐ์ฌ๋ณ ์ธ์ ์ฐจ์ด๋ฅผ ํก์ํ์ง ๋ชปํฉ๋๋ค. ์์ ํ๊ฒ
WindowInsets.safeDrawing๊ธฐ๋ฐ์ผ๋ก ์/ํ๋จ ์ธ์ ์ ํฉ์ฐํ์ธ์.- val offset = if (Build.VERSION.SDK_INT < 35) { - 0.dp - } else { - statusBarHeight + navBarHeight - } - sheetHalfExpandHeight = screenHeight - contentHeight - offset + val safeInsets = WindowInsets.safeDrawing.asPaddingValues() + val systemBarsOffset = safeInsets.calculateTopPadding() + safeInsets.calculateBottomPadding() + sheetHalfExpandHeight = screenHeight - contentHeight - systemBarsOffset๋ค์ํ API(30/33/35) ๋ฐ ์ ์ค์ฒ ๋ด๋น๊ฒ์ด์ /3โbutton ๋ด๋น๊ฒ์ด์ ์์ ์ ๋ฐ ํ์ฅ ์์น๊ฐ ์๋๋๋ก์ธ์ง ๊ฒ์ฆ ๋ถํ๋๋ฆฝ๋๋ค.
515-518: ์์ด์ฝ ์ ๊ทผ์ฑ ๋ผ๋ฒจ ํ์งํ ํ์.
contentDescription = "Mail" / "Setting"์ ํ๋์ฝ๋ฉ/์๋ฌธ์ ๋๋ค.stringResource๋ก ํ์งํ๋ ๋ผ๋ฒจ์ ์ ๊ณตํด ์ฃผ์ธ์.์:
contentDescription = stringResource(id = R.string.cd_mail) contentDescription = stringResource(id = R.string.cd_setting)๋ฌธ์์ด ๋ฆฌ์์ค๊ฐ ์๋ค๋ฉด ์ถ๊ฐ ํ์.
Also applies to: 556-560
604-607: ์ฅ์์ฉ ์ด๋ฏธ์ง๋ contentDescription์ null๋ก.
SkyImage๋ ์ฅ์์ฉ์ผ๋ก ๋ณด์ ๋๋ค. ์คํฌ๋ฆฐ๋ฆฌ๋ ์ค๋ณต ๋ญ๋ ์ ๋ฐฉ์งํ๋ ค๋ฉดcontentDescription = null์ฒ๋ฆฌํ์ธ์.- contentDescription = "IMG_MAIN_SKY", + contentDescription = null,
659-663: CD ์ผ๊ดํ: ์ฅ์์ฉ์ null, ์๋ฏธ ์๋ ์ปจํธ๋กค์ ๋ฆฌ์์ค๋ก.
- ๋งํ์ /๋ณ/๋น ์ํ ์ผ๋ฌ์คํธ ๋ฑ ์ฅ์์ฉ์
contentDescription = null๊ถ์ฅ.AddAlarmButton๋ด ์์ด์ฝ์ ์ ํ ์คํธ๊ฐ ๋ผ๋ฒจ ์ญํ ์ ํ๋ฏ๋ก ์์ด์ฝ CD๋ null์ด ์์ ํฉ๋๋ค(์ค๋ณต ๋ญ๋ ๋ฐฉ์ง).์:
- contentDescription = "IMG_MAIN_SPEECH_BUBBLE", + contentDescription = null,- contentDescription = "Add Alarm", + contentDescription = null,Also applies to: 672-680, 748-758, 827-831
data/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSourceImpl.kt (2)
22-35: ์ค๋ ํ์ ๋ก์ง์ ์๊ฐ ์์ค ๋จ์ผํ/ํ ์คํธ ์ฉ์ด์ฑ ๊ฐ์ .
LocalDate.now()๊ธฐ๋ฐtodayEpoch()๋ ํ ์คํธ/ํ์์กด ๊ฒฝ๊ณ(์์ ์ ํ)์์ ์ทจ์ฝํฉ๋๋ค. ๊ณต์ฉDateProvider/Clock๋ฅผ ์ฃผ์ ํ๊ฑฐ๋UserPreferences์ ๋์ผ ๋ก์ง์ ๋จ์ผ ์์ค๋ก ๋ ธ์ถํด(์:todayEpochDay()), ์ฌ๊ธฐ์๋ ๊ทธ ๊ฐ์ ์ฌ์ฉํ์ธ์. ์ด๋ ๊ฒ ํ๋ฉด ๋๋ฉ์ธ/๋ฐ์ดํฐ์คํ ์ด ๊ฐ ๋ถ์ผ์น ๊ฐ๋ฅ์ฑ์ ์ ๊ฑฐํ ์ ์์ต๋๋ค.
36-36: ์ค๋ณต ์ ํธ ์ ๊ฑฐ ์ ์.
todayEpoch()๋UserPreferences์์ ์ค๋ณต ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค. ํ ๊ณณ์ผ๋ก ๋ชจ์ผ๊ณ ์ฌ์ฌ์ฉํด ์ฃผ์ธ์.
๐ Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
โ Files ignored due to path filters (8)
core/designsystem/src/main/res/drawable-xhdpi/ic_100_buble.pngis excluded by!**/*.pngcore/designsystem/src/main/res/drawable-xhdpi/ic_fortune_delivering_speech_bubble.pngis excluded by!**/*.pngcore/designsystem/src/main/res/drawable-xhdpi/ic_fortune_waiting_speech_bubble.pngis excluded by!**/*.pngcore/designsystem/src/main/res/drawable-xxhdpi/ic_100_buble.pngis excluded by!**/*.pngcore/designsystem/src/main/res/drawable-xxhdpi/ic_fortune_delivering_speech_bubble.pngis excluded by!**/*.pngcore/designsystem/src/main/res/drawable-xxhdpi/ic_fortune_waiting_speech_bubble.pngis excluded by!**/*.pngcore/designsystem/src/main/res/drawable/ic_100_buble.pngis excluded by!**/*.pngproject.dot.pngis excluded by!**/*.png
๐ Files selected for processing (70)
.github/workflows/android_ci.yml(0 hunks)app/build.gradle.kts(2 hunks)app/src/main/AndroidManifest.xml(3 hunks)app/src/main/java/com/yapp/orbit/OrbitApplication.kt(1 hunks)app/src/main/java/com/yapp/orbit/OrbitNavHost.kt(4 hunks)app/src/main/java/com/yapp/orbit/di/AppVersionModule.kt(1 hunks)build-logic/src/main/java/com/yapp/convention/HiltAndroid.kt(1 hunks)build-logic/src/main/java/orbit.android.feature.gradle.kts(0 hunks)core/alarm/src/main/java/com/yapp/alarm/AndroidAlarmScheduler.kt(5 hunks)core/alarm/src/main/java/com/yapp/alarm/receivers/AlarmInteractionActivityReceiver.kt(2 hunks)core/alarm/src/main/java/com/yapp/alarm/receivers/AlarmReceiver.kt(3 hunks)core/alarm/src/main/java/com/yapp/alarm/receivers/RescheduleAlarmReceiver.kt(2 hunks)core/alarm/src/main/java/com/yapp/alarm/scheduler/PostFortuneTaskScheduler.kt(1 hunks)core/alarm/src/main/java/com/yapp/alarm/services/AlarmService.kt(5 hunks)core/common/src/main/java/com/yapp/common/navigation/route/MissionRoute.kt(1 hunks)core/datastore/src/main/java/com/yapp/datastore/UserPreferences.kt(3 hunks)core/designsystem/src/main/res/raw/fortune_loading.json(1 hunks)core/network/src/main/java/com/yapp/network/di/NetworkModule.kt(2 hunks)core/network/src/main/java/com/yapp/network/di/Qualifier.kt(0 hunks)core/ui/src/main/java/com/yapp/ui/component/navigation/NavigationBarScrim.kt(1 hunks)data/src/main/java/com/yapp/data/local/datasource/AlarmLocalDataSource.kt(0 hunks)data/src/main/java/com/yapp/data/local/datasource/AlarmLocalDataSourceImpl.kt(0 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/remote/di/ServiceModule.kt(1 hunks)data/src/main/java/com/yapp/data/repositoryimpl/AlarmRepositoryImpl.kt(0 hunks)data/src/main/java/com/yapp/data/repositoryimpl/FortuneRepositoryImpl.kt(2 hunks)data/src/main/java/com/yapp/data/repositoryimpl/UserInfoRepositoryImpl.kt(1 hunks)domain/src/main/java/com/yapp/domain/model/AlarmDay.kt(2 hunks)domain/src/main/java/com/yapp/domain/model/FortuneCreateStatus.kt(1 hunks)domain/src/main/java/com/yapp/domain/model/MissionMode.kt(1 hunks)domain/src/main/java/com/yapp/domain/repository/AlarmRepository.kt(0 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/AlarmInteractionActivity.kt(2 hunks)feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/action/AlarmActionContract.kt(1 hunks)feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/action/AlarmActionScreen.kt(1 hunks)feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/action/AlarmActionViewModel.kt(3 hunks)feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/snooze/AlarmSnoozeTimerViewModel.kt(1 hunks)feature/fortune/build.gradle.kts(1 hunks)feature/fortune/src/main/java/com/yapp/fortune/FortuneNavGraph.kt(2 hunks)feature/fortune/src/main/java/com/yapp/fortune/FortuneScreen.kt(3 hunks)feature/fortune/src/main/java/com/yapp/fortune/FortuneViewModel.kt(4 hunks)feature/fortune/src/main/java/com/yapp/fortune/di/SchedulerModule.kt(1 hunks)feature/fortune/src/main/java/com/yapp/fortune/page/FortunePager.kt(1 hunks)feature/fortune/src/main/java/com/yapp/fortune/scheduler/WorkManagerPostFortuneTaskScheduler.kt(1 hunks)feature/fortune/src/main/java/com/yapp/fortune/worker/PostFortuneWorker.kt(1 hunks)feature/home/build.gradle.kts(1 hunks)feature/home/src/main/AndroidManifest.xml(1 hunks)feature/home/src/main/java/com/yapp/home/HomeContract.kt(2 hunks)feature/home/src/main/java/com/yapp/home/HomeScreen.kt(17 hunks)feature/home/src/main/java/com/yapp/home/HomeViewModel.kt(9 hunks)feature/home/src/main/java/com/yapp/home/alarm/addedit/AlarmAddEditScreen.kt(2 hunks)feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmMissionBottomSheet.kt(10 hunks)feature/home/src/main/java/com/yapp/home/component/bottomsheet/AlarmListBottomSheet.kt(3 hunks)feature/home/src/main/java/com/yapp/home/component/bottomsheet/UpdateNoticeBottomSheet.kt(1 hunks)feature/home/src/main/res/values/strings.xml(2 hunks)feature/mission/src/main/java/com/yapp/mission/MissionContract.kt(0 hunks)feature/mission/src/main/java/com/yapp/mission/MissionNavGraph.kt(2 hunks)feature/mission/src/main/java/com/yapp/mission/MissionScreen.kt(0 hunks)feature/mission/src/main/java/com/yapp/mission/MissionViewModel.kt(2 hunks)feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingAccessScreen.kt(0 hunks)feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingBirthdayScreen.kt(0 hunks)feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingCompleteScreen2.kt(0 hunks)feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingGenderScreen.kt(3 hunks)feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingNavGraph.kt(1 hunks)feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingViewModel.kt(1 hunks)gradle/libs.versions.toml(4 hunks)
๐ค Files with no reviewable changes (12)
- feature/mission/src/main/java/com/yapp/mission/MissionContract.kt
- domain/src/main/java/com/yapp/domain/repository/AlarmRepository.kt
- feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingBirthdayScreen.kt
- .github/workflows/android_ci.yml
- data/src/main/java/com/yapp/data/local/datasource/AlarmLocalDataSource.kt
- build-logic/src/main/java/orbit.android.feature.gradle.kts
- data/src/main/java/com/yapp/data/repositoryimpl/AlarmRepositoryImpl.kt
- feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingCompleteScreen2.kt
- feature/mission/src/main/java/com/yapp/mission/MissionScreen.kt
- feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingAccessScreen.kt
- data/src/main/java/com/yapp/data/local/datasource/AlarmLocalDataSourceImpl.kt
- core/network/src/main/java/com/yapp/network/di/Qualifier.kt
๐งฐ Additional context used
๐ง Learnings (4)
๐ Learning: 2025-07-27T15:20:35.256Z
Learnt from: DongChyeon
PR: YAPP-Github/Orbit-Android#238
File: feature/mission/src/main/java/com/yapp/mission/MissionScreen.kt:118-120
Timestamp: 2025-07-27T15:20:35.256Z
Learning: MissionRoute์ MissionScreen์ด ๊ฐ์ ํ์ผ(feature/mission/src/main/java/com/yapp/mission/MissionScreen.kt)์ ์์ ๋, MissionRoute์์ BackHandler๋ฅผ ์ฌ์ฉํ๋ฉด ํ์ผ ๋ ๋ฒจ์ import ๋ฌธ์ ์ ์ง๋์ด์ผ ํจ.
Applied to files:
feature/mission/src/main/java/com/yapp/mission/MissionNavGraph.ktcore/common/src/main/java/com/yapp/common/navigation/route/MissionRoute.kt
๐ Learning: 2025-09-14T15:32:32.628Z
Learnt from: DongChyeon
PR: YAPP-Github/Orbit-Android#252
File: feature/fortune/src/main/java/com/yapp/fortune/worker/PostFortuneWorker.kt:24-56
Timestamp: 2025-09-14T15:32:32.628Z
Learning: ์ด์ธ ์์ฒญ ๊ฐ์๋ ์ต์ 1๋ถ ๊ฐ๊ฒฉ์ด ๋ณด์ฅ๋์ด ์์ด์ PostFortuneWorker์์ ๋์์ฑ/์์์ฑ ๋ฌธ์ ๋ฅผ ๊ณ ๋ คํ์ง ์์๋ ๋จ
Applied to files:
feature/fortune/src/main/java/com/yapp/fortune/worker/PostFortuneWorker.kt
๐ Learning: 2025-07-23T10:29:14.146Z
Learnt from: DongChyeon
PR: YAPP-Github/Orbit-Android#234
File: feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmMissionBottomSheet.kt:73-76
Timestamp: 2025-07-23T10:29:14.146Z
Learning: AlarmMissionBottomSheet์์ missionType/missionCount ํ๋ผ๋ฏธํฐ๋ ํ์ฌ ์ ์ฅ๋ ๊ฐ์ UI์ ํ์ํ๊ธฐ ์ํด ์ฌ์ฉ๋๊ณ , selectedMissionType/selectedMissionCount๋ ์ฌ์ฉ์๊ฐ ๋ณ๊ฒฝ ์ค์ธ ๋ด๋ถ ์์
์ํ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ค. onDone์ด๋ onSave ์ฝ๋ฐฑ์ ํตํด ๋ช
์์ ์ผ๋ก ์ ์ฅํ ๋๋ง ๋ณ๊ฒฝ์ฌํญ์ด ๋ฐ์๋๋ UX ํจํด์ด๋ค.
Applied to files:
feature/home/src/main/res/values/strings.xmlfeature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmMissionBottomSheet.kt
๐ Learning: 2025-09-15T07:43:50.275Z
Learnt from: DongChyeon
PR: YAPP-Github/Orbit-Android#254
File: data/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSourceImpl.kt:22-34
Timestamp: 2025-09-15T07:43:50.275Z
Learning: FortuneCreateStatusFlow์์ todayEpoch()๋ฅผ combine ๋ด๋ถ์์ ์ง์ ํธ์ถํ๋ ๊ฒ์ด ์ถฉ๋ถํ ์ด์ : ์ด์ธ ์์ฑํ ๋๋ง๋ค fortuneDateEpochFlow๊ฐ ๋ณ๊ฒฝ๋์ด combine์ด ์ฌํ๊ฐ๋๋ฏ๋ก, ๊ทธ ์๊ฐ์ todayEpoch() ๊ณ์ฐ์ผ๋ก ์ถฉ๋ถํจ. ์ด์ธ ์์ฒญ ๊ฐ๊ฒฉ ์ ์ฝ์ผ๋ก ์ธํด ์์ ๋กค์ค๋ฒ ๋ฌธ์ ๋ ์ค์ฉ์ ์ผ๋ก ๋ฐ์ํ์ง ์์.
Applied to files:
feature/home/src/main/java/com/yapp/home/HomeViewModel.kt
๐งฌ Code graph analysis (10)
feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/AlarmInteractionActivity.kt (2)
feature/alarm-interaction/src/main/java/com/yapp/alarm/interaction/AlarmInteractionNavGraph.kt (1)
alarmInteractionNavGraph(33-69)core/ui/src/main/java/com/yapp/ui/component/navigation/NavigationBarScrim.kt (1)
NavigationBarScrim(16-26)
feature/fortune/src/main/java/com/yapp/fortune/page/FortunePager.kt (1)
feature/fortune/src/main/java/com/yapp/fortune/page/FortuneCompletePage.kt (1)
FortuneCompletePage(28-104)
feature/home/src/main/java/com/yapp/home/component/bottomsheet/UpdateNoticeBottomSheet.kt (1)
core/designsystem/src/main/java/com/yapp/designsystem/theme/Theme.kt (1)
OrbitTheme(12-28)
feature/fortune/src/main/java/com/yapp/fortune/FortuneScreen.kt (2)
core/ui/src/main/java/com/yapp/ui/component/lottie/LottieAnimation.kt (1)
LottieAnimation(22-85)core/designsystem/src/main/java/com/yapp/designsystem/theme/Theme.kt (1)
OrbitTheme(12-28)
feature/home/src/main/java/com/yapp/home/HomeScreen.kt (2)
feature/home/src/main/java/com/yapp/home/HomeViewModel.kt (1)
processAction(55-87)feature/home/src/main/java/com/yapp/home/component/bottomsheet/UpdateNoticeBottomSheet.kt (1)
UpdateNoticeBottomSheet(51-139)
feature/home/src/main/java/com/yapp/home/alarm/addedit/AlarmAddEditScreen.kt (1)
core/ui/src/main/java/com/yapp/ui/component/bottomsheet/OrbitBottomSheetLayout.kt (1)
OrbitBottomSheetLayout(31-59)
feature/home/src/main/java/com/yapp/home/component/bottomsheet/AlarmListBottomSheet.kt (2)
feature/home/src/main/java/com/yapp/home/component/AlarmListDropDownMenu.kt (1)
AlarmListDropDownMenu(43-72)feature/home/src/main/java/com/yapp/home/component/AlarmSortDropDownMenu.kt (1)
AlarmSortDropDownMenu(36-67)
feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingGenderScreen.kt (4)
core/ui/src/main/java/com/yapp/ui/component/bottomsheet/OrbitBottomSheetLayout.kt (1)
OrbitBottomSheetLayout(31-59)feature/onboarding/src/main/java/com/yapp/onboarding/OnBoardingScreen.kt (1)
OnboardingScreen(14-54)feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingViewModel.kt (1)
processAction(49-67)core/ui/src/main/java/com/yapp/ui/toggle/OrbitGenderToggle.kt (1)
OrbitGenderToggle(30-98)
core/datastore/src/main/java/com/yapp/datastore/UserPreferences.kt (1)
data/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSourceImpl.kt (1)
todayEpoch(36-36)
data/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSourceImpl.kt (1)
core/datastore/src/main/java/com/yapp/datastore/UserPreferences.kt (1)
todayEpoch(44-44)
๐ช detekt (1.23.8)
app/src/main/java/com/yapp/orbit/OrbitApplication.kt
[warning] 11-11: An empty default constructor can be removed.
(detekt.empty-blocks.EmptyDefaultConstructor)
core/alarm/src/main/java/com/yapp/alarm/receivers/RescheduleAlarmReceiver.kt
Outdated
Show resolved
Hide resolved
feature/fortune/src/main/java/com/yapp/fortune/worker/PostFortuneWorker.kt
Show resolved
Hide resolved
feature/home/src/main/java/com/yapp/home/component/bottomsheet/AlarmListBottomSheet.kt
Show resolved
Hide resolved
feature/home/src/main/java/com/yapp/home/component/bottomsheet/AlarmListBottomSheet.kt
Show resolved
Hide resolved
feature/onboarding/src/main/java/com/yapp/onboarding/OnboardingViewModel.kt
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
โป๏ธ Duplicate comments (3)
feature/home/src/main/java/com/yapp/home/component/bottomsheet/AlarmListBottomSheet.kt (2)
102-114: snapshotFlow ์ค๋ณต ์ด๋ฒคํธ ๋ฐฉ์ง ๊ฐ์ ํ์ํ์ฌ ๊ตฌํ์์๋
distinctUntilChanged()๋ฅผ ์ ์ฉํ์ง๋ง,LaunchedEffect์ key๊ฐ ์ฌ์ ํUnit์ ๋๋ค.sheetState๋ฅผ key๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์์ ํฉ๋๋ค.๋ค์๊ณผ ๊ฐ์ด ์์ ํ์ธ์:
- LaunchedEffect(Unit) { + LaunchedEffect(sheetState) { snapshotFlow { sheetState.currentValue } .distinctUntilChanged() .collectLatest { value ->
98-98: Hidden ์ํ ์ ์ด ๋ฐฉ์ง ํ์
confirmValueChange์ ๊ฑฐ๋ก ์ฌ์ฉ์๊ฐ ๋๋๊ทธํ์ฌ Hidden ์ํ๋ก ์ ์ดํ ์ ์์ต๋๋ค. ์ํธ๊ฐ ํญ์ ํ์๋์ด์ผ ํ๋ค๋ฉด Hidden ์ํ๋ฅผ ๋ช ์์ ์ผ๋ก ์ฐจ๋จํด์ผ ํฉ๋๋ค.๋ค์ ์ค ํ๋๋ฅผ ์ ์ฉํ์ธ์:
์ต์ 1: Hidden ์ํ ๊ฑด๋๋ฐ๊ธฐ (๊ถ์ฅ)
- val sheetState = rememberStandardBottomSheetState() + val sheetState = rememberStandardBottomSheetState( + skipHiddenState = true + )์ต์ 2: confirmValueChange๋ก ๋ช ์์ ์ฐจ๋จ
- val sheetState = rememberStandardBottomSheetState() + val sheetState = rememberStandardBottomSheetState( + confirmValueChange = { it != SheetValue.Hidden } + )core/alarm/src/main/java/com/yapp/alarm/receivers/RescheduleAlarmReceiver.kt (1)
30-31: goAsync ์ ์ฉ ๊ตฟ + ์ฑ ์ ๋ฐ์ดํธ ํ ์ฌ์ค์ผ์ค๋ ํจ๊ป ์ฒ๋ฆฌ ์ ์๋ถํ ํ๋ง ์ฒ๋ฆฌํ๋ฉด ์ฑ ์ ๋ฐ์ดํธ ์งํ ์๋ ์ฌ์ค์ ์ด ๋๋ฝ๋ ์ ์์ต๋๋ค. ACTION_MY_PACKAGE_REPLACED๋ ํจ๊ป ์์ ํด ๋์ผ ๋ก์ง์ ํ์ฐ๋ ๊ฑธ ๊ถ์ฅํฉ๋๋ค. (์ด์ ๋ฆฌ๋ทฐ ์ฝ๋ฉํธ์ ๋์ผ ์ ์)
- if (intent.action == Intent.ACTION_BOOT_COMPLETED) { + if (intent.action == Intent.ACTION_BOOT_COMPLETED || intent.action == Intent.ACTION_MY_PACKAGE_REPLACED) { val pending = goAsync() rescheduleAlarm(pending) }
๐งน Nitpick comments (1)
core/alarm/src/main/java/com/yapp/alarm/receivers/RescheduleAlarmReceiver.kt (1)
35-44: ์์ธ ๋ก๊น ์ถ๊ฐ๋ก ๋ฌธ์ ์ง๋จ์ฑ ๊ฐ์ ์ ์ํ์ฌ ์์ธ๊ฐ ์ผ์ผ์ ธ ์์ธ ํ์ ์ด ์ด๋ ต์ต๋๋ค. catch์์ ๋ก๊น ํ finish ๋ณด์ฅ ์ ์ง ๊ถ์ฅ.
- CoroutineScope(Dispatchers.IO + SupervisorJob()).launch { - try { - val alarms = alarmUseCase.getAllAlarms().first() - alarms - .filter { it.isAlarmActive } - .forEach { alarm -> androidAlarmScheduler.scheduleAlarm(alarm) } - } finally { - pendingResult.finish() - } - } + CoroutineScope(Dispatchers.IO + SupervisorJob()).launch { + try { + val alarms = alarmUseCase.getAllAlarms().first() + alarms + .filter { it.isAlarmActive } + .forEach { alarm -> androidAlarmScheduler.scheduleAlarm(alarm) } + } catch (t: Throwable) { + android.util.Log.e("RescheduleAlarmReceiver", "Failed to reschedule alarms", t) + } finally { + pendingResult.finish() + } + }
๐ Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
๐ Files selected for processing (2)
core/alarm/src/main/java/com/yapp/alarm/receivers/RescheduleAlarmReceiver.kt(2 hunks)feature/home/src/main/java/com/yapp/home/component/bottomsheet/AlarmListBottomSheet.kt(4 hunks)
๐งฐ Additional context used
๐งฌ Code graph analysis (1)
feature/home/src/main/java/com/yapp/home/component/bottomsheet/AlarmListBottomSheet.kt (2)
feature/home/src/main/java/com/yapp/home/component/AlarmListDropDownMenu.kt (1)
AlarmListDropDownMenu(43-72)feature/home/src/main/java/com/yapp/home/component/AlarmSortDropDownMenu.kt (1)
AlarmSortDropDownMenu(36-67)
โฐ 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). (2)
- GitHub Check: build
- GitHub Check: Continuous Deployment
๐ Additional comments (4)
feature/home/src/main/java/com/yapp/home/component/bottomsheet/AlarmListBottomSheet.kt (2)
329-341: ๋๋กญ๋ค์ด ๋ฉ๋ด ์กฐ๊ฑด๋ถ ๋ ๋๋ง ์ ๊ฑฐ ํ์ธ
AlarmListDropDownMenu์AlarmSortDropDownMenu๊ฐ ์ด์ ํญ์ ๋ ๋๋ง๋๋ฉฐ,expanded์ํ๋ง ์ ๋ฌ๋ฉ๋๋ค. ์ด๋ ์ฑ๋ฅ์ ๋ฌธ์ ๊ฐ ์์ง๋ง, ๋ ๋ฉ๋ด๊ฐ ๋์์ ์ด๋ฆด ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค.๋ ๋ฉ๋ด๊ฐ ๋์์ ์ด๋ฆฌ์ง ์๋๋ก ์ํ ๊ด๋ฆฌ๊ฐ ์ ์ ํ ๋๊ณ ์๋์ง ํ์ธ์ด ํ์ํฉ๋๋ค. ํนํ
menuExpanded์sortDropDownMenuExpanded๊ฐ ์ํธ ๋ฐฐํ์ ์ผ๋ก ๊ด๋ฆฌ๋๋์ง ๊ฒ์ฆํ์ธ์.
93-93: onExpanded ์ฝ๋ฐฑ ์ฌ์ฉ ํ์ธ โ ํด๊ฒฐ๋จfeature/home/src/main/java/com/yapp/home/HomeScreen.kt (lines 394โ396)์์ onExpanded๊ฐ ํธ์ถ๋์ด processAction(HomeContract.Action.HideToolTip)๋ฅผ ์คํํฉ๋๋ค. ์์ ๋ถํ์.
core/alarm/src/main/java/com/yapp/alarm/receivers/RescheduleAlarmReceiver.kt (2)
11-12: ํ์ import ์ถ๊ฐ ์ ์ SupervisorJob, flow.first ๋์ ๋ชจ๋ ์ํฉ์ ๋ง๊ณ ๐
29-33: Manifest ์ค์ ํ์ธ: RECEIVE_BOOT_COMPLETEDยทintent-filterยทexported ํ์ธ๋จapp/src/main/AndroidManifest.xml์ RECEIVE_BOOT_COMPLETED ๊ถํ(๋ผ์ธ 11)๊ณผ RescheduleAlarmReceiver ๋ฆฌ์๋ฒ ์ ์ธ(๋ผ์ธ 72โ76) โ intent-filter(android.intent.action.BOOT_COMPLETED) ๋ฐ android:exported="true"(๋ผ์ธ 73)๊ฐ ์กด์ฌํ๋ฏ๋ก BOOT_COMPLETED ์์ ์ค์ ์ ์ถฉ์กฑ๋ฉ๋๋ค.
Related issue ๐
closed #<issue_number>
์ด๋ค ๋ณ๊ฒฝ์ฌํญ์ด ์์๋์?
CheckPoint โ
PR์ด ๋ค์ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ๋์ง ํ์ธํ์ธ์.
Work Description โ๏ธ
Uncompleted Tasks ๐
To Reviewers ๐ข
Summary by CodeRabbit
New Features
UI/UX
Improvements
Permissions
Chores