Skip to content

Conversation

@comst19
Copy link
Collaborator

@comst19 comst19 commented Jan 15, 2026

1. ⭐️ 변경된 내용

  • 서비스 일시 중단 팝업
  • remote config 변경 사항 실시간으로 반영할 수 있도록 변경
  • 코루틴 스코프에서 join 제거

2. 🖼️ 스크린샷(선택)

image

3. 💡 알게된 부분

4. 📌 이 부분은 꼭 봐주세요!

  • firebase remote config에서 값 수정하여 사용

Summary by CodeRabbit

  • New Features
    • Maintenance mode support: app detects maintenance windows and shows a dedicated dialog with the maintenance period and an exit action.
    • New localized maintenance strings added.
    • App refreshes maintenance status on startup and on resume; UI blurs and shows an overlay when a maintenance/update popup is active.
    • Maintenance dialog takes precedence over the force-update dialog.
  • UI
    • Dialogs can display an optional description block for richer messaging.

✏️ Tip: You can customize this high-level summary in your review settings.

@comst19 comst19 requested a review from tgyuuAn January 15, 2026 08:19
@comst19 comst19 self-assigned this Jan 15, 2026
@comst19 comst19 added 리뷰 원해요🔥 피어의 리뷰를 기다리는 ing.. 🔥 ㅁㅅ민수 labels Jan 15, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 15, 2026

📝 Walkthrough

Walkthrough

Adds maintenance-period support across layers: new domain model and network DTO, Remote Config key and init, repository method, ViewModel state and refresh flow, MainActivity/PieceApp wiring, a MaintenanceDialog UI, design-system dialog description support, and new string resources.

Changes

Cohort / File(s) Summary
Domain models & repo
core/domain/src/main/java/com/puzzle/domain/model/configure/MaintenancePeriod.kt, core/domain/src/main/java/com/puzzle/domain/repository/ConfigureRepository.kt
New MaintenancePeriod data class and repository API suspend fun getMaintenancePeriod(): MaintenancePeriod.
Network model
core/network/src/main/java/com/puzzle/network/model/configure/GetMaintenancePeriodInfoResponse.kt
New serializable DTO GetMaintenancePeriodInfoResponse with toDomain() mapping to MaintenancePeriod.
Data source & constants
core/network/src/main/java/com/puzzle/network/source/configure/ConfigureDataSource.kt
Added MAINTENANCE_PERIOD key and Remote Config init (minFetchIntervalInSeconds=0) plus update listener to activate config on updates — review runtime Remote Config behavior.
Repository implementation
core/data/src/main/java/com/puzzle/data/repository/ConfigureRepositoryImpl.kt
Implemented getMaintenancePeriod() calling data source and mapping response to domain.
ViewModel & lifecycle
presentation/src/main/java/com/puzzle/presentation/MainViewModel.kt, presentation/src/main/java/com/puzzle/presentation/MainActivity.kt
New maintenancePeriod StateFlow, checkMaintenancePeriod() and refreshAppStatus() added; MainActivity observes state and calls refreshAppStatus() in onResume().
App UI wiring
presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt
PieceApp signature updated to accept MaintenancePeriod?; conditional rendering of MaintenanceDialog and blur overlay when a popup shows.
Maintenance dialog UI
presentation/src/main/java/com/puzzle/presentation/maintenance/MaintenanceDialog.kt
New MaintenanceDialog composable rendering title, subtext, colored period description, and an exit button that calls finishAffinity().
Force update dialog
presentation/src/main/java/com/puzzle/presentation/update/ForceUpdateDialog.kt
ForceUpdateDialog signature changed to no-arg and now always renders; isShowForceUpdateDialog made internal. Review visibility/usage changes.
Design system dialog
core/designsystem/src/main/java/com/puzzle/designsystem/component/Dialog.kt
Added optional description: AnnotatedString? = null to PieceDialogDefaultTop overloads and rendering for description; previews updated.
String resources
core/designsystem/src/main/res/values/strings.xml
Added maintenance_title, maintenance_subtext, maintenance_description_prefix, and maintenance_label.

Sequence Diagram

sequenceDiagram
    participant Activity as MainActivity
    participant ViewModel as MainViewModel
    participant Repo as ConfigureRepository
    participant DataSource as ConfigureDataSource
    participant Firebase as FirebaseRemoteConfig
    participant UI as PieceApp / MaintenanceDialog

    Activity->>ViewModel: onResume() -> refreshAppStatus()
    ViewModel->>ViewModel: checkMaintenancePeriod()
    ViewModel->>Repo: getMaintenancePeriod()
    Repo->>DataSource: queryRemoteConfig(MAINTENANCE_PERIOD)
    DataSource->>Firebase: fetch/activate
    Firebase-->>DataSource: maintenancePeriod string
    DataSource-->>Repo: GetMaintenancePeriodInfoResponse
    Repo-->>ViewModel: MaintenancePeriod (toDomain())
    ViewModel->>Activity/UI: emit maintenancePeriod state
    UI->>UI: show MaintenanceDialog if non-blank
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

기능 ⚒️

Suggested reviewers

  • tgyuuAn
  • kkh725

Poem

🐇 I hopped through remote-config air,
I fetched a period and set it there,
A dialog blooms to say “stand by,”
Users read, I twitch my ear and sigh,
I thump — maintenance found, carrots spared.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main feature: implementing a service maintenance popup, which aligns with the core changes across the PR (new MaintenanceDialog, MaintenancePeriod model, and integration into PieceApp).
Description check ✅ Passed PR description follows the template with all 4 required sections completed; sections 3 and 4 provide meaningful context about implementation details.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In
`@core/network/src/main/java/com/puzzle/network/source/configure/ConfigureDataSource.kt`:
- Around line 24-35: The init block in ConfigureDataSource.kt currently swallows
Remote Config errors and uses minimumFetchIntervalInSeconds = 0; update the
remoteConfig.addOnConfigUpdateListener implementation so onError(error:
FirebaseRemoteConfigException) logs the exception (use your app
logger/Timber/Log.e) including contextual text, and avoid silently discarding
it; also change minimumFetchIntervalInSeconds from 0 to a production-safe
default (e.g., 3600) and/or make it configurable via build flags (keep 0 only
for debug builds) so fetches aren’t throttled in production; ensure
remoteConfig.activate() remains called only on successful onUpdate.

In `@presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt`:
- Around line 116-118: The current composition allows both MaintenanceDialog and
ForceUpdateDialog to display simultaneously (NetworkScreen,
MaintenanceDialog(maintenancePeriod?.maintenancePeriod),
ForceUpdateDialog(forceUpdate)); to fix this, ensure only the higher-priority
dialog shows: either reorder to compose ForceUpdateDialog before
MaintenanceDialog so it renders below maintenance, or add conditional logic so
when maintenancePeriod is non-null you only call MaintenanceDialog (which
triggers finishAffinity()), else if forceUpdate is non-null call
ForceUpdateDialog; reference the composables MaintenanceDialog,
ForceUpdateDialog and the state props maintenancePeriod and forceUpdate when
implementing the change.
♻️ Duplicate comments (2)
core/designsystem/src/main/java/com/puzzle/designsystem/component/Dialog.kt (2)

156-202: Same duplication applies here.

This overload also contains the same duplicated description rendering logic. The suggested DescriptionBox extraction would apply here as well.


204-250: Same duplication applies here.

This overload also contains the same duplicated description rendering logic.

🧹 Nitpick comments (4)
core/domain/src/main/java/com/puzzle/domain/model/configure/MaintenancePeriod.kt (1)

3-5: Consider renaming the property to avoid redundancy.

The property name maintenancePeriod is redundant with the class name, resulting in MaintenancePeriod.maintenancePeriod at usage sites. A simpler name like period or description would improve readability.

♻️ Suggested improvement
 data class MaintenancePeriod (
-    val maintenancePeriod: String
+    val period: String
 )
presentation/src/main/java/com/puzzle/presentation/maintenance/MaintenanceDialog.kt (1)

44-54: Consider handling the case where activity is null.

While the safe call activity?.finishAffinity() prevents a crash, clicking the button when activity is null results in a silent no-op. In the context of PieceApp, LocalContext.current should always be an Activity, but adding a fallback (e.g., logging or showing a toast) could help diagnose issues in edge cases.

♻️ Optional: Add fallback handling
 dialogBottom = {
     PieceSolidButton(
         label = stringResource(id = R.string.maintenance_label),
         onClick = {
-            activity?.finishAffinity()
+            activity?.finishAffinity() ?: run {
+                // Fallback: close via system back if activity is unavailable
+                (context as? Activity)?.finish()
+            }
         },
         modifier = Modifier
             .fillMaxWidth()
             .padding(bottom = 20.dp, top = 12.dp),
     )
 }
core/designsystem/src/main/java/com/puzzle/designsystem/component/Dialog.kt (2)

85-104: Redundant background modifier on Text.

The background(PieceTheme.colors.light3) modifier on line 101 is redundant since the parent Box already applies the same background at line 91. This duplication exists in all 4 overloads.

♻️ Proposed fix
         description?.let {
             Box(
                 contentAlignment = Alignment.Center,
                 modifier = Modifier
                     .padding(top = 4.dp)
                     .fillMaxWidth()
                     .background(PieceTheme.colors.light3)
                     .padding(vertical = 12.dp),
             ) {
                 Text(
                     text = it,
                     color = PieceTheme.colors.dark3,
                     style = PieceTheme.typography.bodySM,
                     textAlign = TextAlign.Center,
                     modifier = Modifier
                         .fillMaxWidth()
-                        .background(PieceTheme.colors.light3)
                 )
             }
         }

108-154: Identical rendering logic duplicated across overloads.

The description rendering block (lines 133-152) is identical to the one in the previous overload. Consider extracting this to a private composable to reduce duplication.

♻️ Suggested extraction
`@Composable`
private fun DescriptionBox(description: AnnotatedString) {
    Box(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            .padding(top = 4.dp)
            .fillMaxWidth()
            .background(PieceTheme.colors.light3)
            .padding(vertical = 12.dp),
    ) {
        Text(
            text = description,
            color = PieceTheme.colors.dark3,
            style = PieceTheme.typography.bodySM,
            textAlign = TextAlign.Center,
            modifier = Modifier.fillMaxWidth()
        )
    }
}

Then each overload can simply call:

description?.let { DescriptionBox(it) }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4fd56d6 and c899cde.

📒 Files selected for processing (11)
  • core/data/src/main/java/com/puzzle/data/repository/ConfigureRepositoryImpl.kt
  • core/designsystem/src/main/java/com/puzzle/designsystem/component/Dialog.kt
  • core/designsystem/src/main/res/values/strings.xml
  • core/domain/src/main/java/com/puzzle/domain/model/configure/MaintenancePeriod.kt
  • core/domain/src/main/java/com/puzzle/domain/repository/ConfigureRepository.kt
  • core/network/src/main/java/com/puzzle/network/model/configure/GetMaintenancePeriodInfoResponse.kt
  • core/network/src/main/java/com/puzzle/network/source/configure/ConfigureDataSource.kt
  • presentation/src/main/java/com/puzzle/presentation/MainActivity.kt
  • presentation/src/main/java/com/puzzle/presentation/MainViewModel.kt
  • presentation/src/main/java/com/puzzle/presentation/maintenance/MaintenanceDialog.kt
  • presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt
🧰 Additional context used
🧬 Code graph analysis (2)
presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt (1)
presentation/src/main/java/com/puzzle/presentation/maintenance/MaintenanceDialog.kt (1)
  • MaintenanceDialog (20-56)
presentation/src/main/java/com/puzzle/presentation/MainViewModel.kt (5)
core/network/src/main/java/com/puzzle/network/api/PieceApi.kt (1)
  • loadTerms (70-71)
core/data/src/main/java/com/puzzle/data/repository/TermsRepositoryImpl.kt (1)
  • loadTerms (23-30)
core/network/src/main/java/com/puzzle/network/source/term/TermDataSource.kt (2)
  • loadTerms (5-8)
  • loadTerms (6-6)
core/network/src/main/java/com/puzzle/network/source/term/TermDataSourceImpl.kt (1)
  • loadTerms (14-14)
core/common/src/main/java/com/puzzle/common/ResultUtil.kt (1)
  • suspendRunCatching (5-13)
🪛 detekt (1.23.8)
core/network/src/main/java/com/puzzle/network/source/configure/ConfigureDataSource.kt

[warning] 33-33: This empty block of code can be removed.

(detekt.empty-blocks.EmptyFunctionBlock)

⏰ 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: build
🔇 Additional comments (14)
core/domain/src/main/java/com/puzzle/domain/repository/ConfigureRepository.kt (1)

4-8: LGTM!

The new getMaintenancePeriod() method follows the same pattern as the existing getUpdateInfo() method. Clean and consistent interface extension.

core/network/src/main/java/com/puzzle/network/source/configure/ConfigureDataSource.kt (1)

63-66: LGTM!

The new MAINTENANCE_PERIOD constant follows the existing pattern established by FORCE_UPDATE.

core/designsystem/src/main/res/values/strings.xml (1)

320-326: LGTM!

The new maintenance strings are well-structured and follow the existing pattern in the file. The user-facing text is clear and appropriate for a maintenance notification dialog.

core/network/src/main/java/com/puzzle/network/model/configure/GetMaintenancePeriodInfoResponse.kt (1)

1-13: LGTM!

The network model follows the established project pattern with @Serializable annotation and a toDomain() mapper. The default empty string for maintenancePeriod is appropriate for handling cases when no maintenance is scheduled. This dependency direction (network → domain) is consistent across the network layer.

core/data/src/main/java/com/puzzle/data/repository/ConfigureRepositoryImpl.kt (1)

22-27: LGTM!

The implementation follows the established pattern of getUpdateInfo() and correctly retrieves the maintenance period configuration using the data source with proper domain mapping.

presentation/src/main/java/com/puzzle/presentation/MainViewModel.kt (4)

54-56: LGTM!

State declaration follows the same pattern as forceUpdate with proper encapsulation.


95-101: LGTM!

Good refactor to parallel execution using coroutineScope. All launched coroutines will complete before the function returns, which is the correct behavior for initialization.


103-106: LGTM!

The refreshAppStatus() function correctly groups the version and maintenance checks for resumption scenarios, enabling real-time remote config reflection.


116-122: LGTM!

The implementation follows the same error-handling pattern as checkMinVersion(). The UI layer (MaintenanceDialog) correctly handles empty/blank strings by checking isNullOrBlank() before rendering.

presentation/src/main/java/com/puzzle/presentation/maintenance/MaintenanceDialog.kt (1)

20-26: LGTM!

Good defensive programming with the early return for null/blank strings and safe cast to Activity.

presentation/src/main/java/com/puzzle/presentation/MainActivity.kt (2)

99-99: LGTM!

State observation and passing follows the established pattern used for forceUpdate.

Also applies to: 108-108


155-160: LGTM!

Using lifecycleScope ensures proper coroutine cancellation when the activity is destroyed. The approach of refreshing app status on every resume is appropriate for real-time remote config updates, and StateFlow will deduplicate identical values to prevent unnecessary recompositions.

presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt (1)

54-54: LGTM!

The nullable parameter follows the same pattern as forceUpdate and allows for a clean no-maintenance state.

core/designsystem/src/main/java/com/puzzle/designsystem/component/Dialog.kt (1)

431-451: LGTM!

The preview correctly demonstrates the new description parameter usage, which is helpful for visual verification of the feature.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +24 to +35
init {
val configSettings = remoteConfigSettings {
minimumFetchIntervalInSeconds = 0
}
remoteConfig.setConfigSettingsAsync(configSettings)
remoteConfig.addOnConfigUpdateListener(object : ConfigUpdateListener {
override fun onUpdate(configUpdate: ConfigUpdate) {
remoteConfig.activate()
}
override fun onError(error: FirebaseRemoteConfigException) {}
})
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Silent error handling could mask configuration issues.

The empty onError handler will silently swallow FirebaseRemoteConfigException errors, making it difficult to diagnose connectivity or configuration issues in production. Consider logging the error at minimum.

Also, minimumFetchIntervalInSeconds = 0 means every fetch request will hit the server, which could lead to throttling in production. Firebase recommends longer intervals (e.g., 3600 seconds) for production.

🔧 Suggested improvement
 init {
     val configSettings = remoteConfigSettings {
-        minimumFetchIntervalInSeconds = 0
+        minimumFetchIntervalInSeconds = if (BuildConfig.DEBUG) 0 else 3600
     }
     remoteConfig.setConfigSettingsAsync(configSettings)
     remoteConfig.addOnConfigUpdateListener(object : ConfigUpdateListener {
         override fun onUpdate(configUpdate: ConfigUpdate) {
             remoteConfig.activate()
         }
-        override fun onError(error: FirebaseRemoteConfigException) {}
+        override fun onError(error: FirebaseRemoteConfigException) {
+            // Log error for observability; real-time updates will retry automatically
+            android.util.Log.w("ConfigDataSource", "Remote config update failed", error)
+        }
     })
 }
🧰 Tools
🪛 detekt (1.23.8)

[warning] 33-33: This empty block of code can be removed.

(detekt.empty-blocks.EmptyFunctionBlock)

🤖 Prompt for AI Agents
In
`@core/network/src/main/java/com/puzzle/network/source/configure/ConfigureDataSource.kt`
around lines 24 - 35, The init block in ConfigureDataSource.kt currently
swallows Remote Config errors and uses minimumFetchIntervalInSeconds = 0; update
the remoteConfig.addOnConfigUpdateListener implementation so onError(error:
FirebaseRemoteConfigException) logs the exception (use your app
logger/Timber/Log.e) including contextual text, and avoid silently discarding
it; also change minimumFetchIntervalInSeconds from 0 to a production-safe
default (e.g., 3600) and/or make it configurable via build flags (keep 0 only
for debug builds) so fetches aren’t throttled in production; ensure
remoteConfig.activate() remains called only on successful onUpdate.

Copy link

@coderabbitai coderabbitai bot left a 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

🤖 Fix all issues with AI agents
In `@presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt`:
- Around line 117-121: The code accesses maintenancePeriod.maintenancePeriod
without a safe-call so Kotlin won't smart-cast the nullable receiver; fix by
extracting the inner string to a local val (e.g., maintenanceText =
maintenancePeriod?.maintenancePeriod) and use that in the conditional: if
(!maintenanceText.isNullOrBlank()) call MaintenanceDialog(maintenanceText) else
call ForceUpdateDialog(forceUpdate); this ensures null-safety and correct
smart-casting.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c899cde and 48e3a50.

📒 Files selected for processing (2)
  • presentation/src/main/java/com/puzzle/presentation/maintenance/MaintenanceDialog.kt
  • presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • presentation/src/main/java/com/puzzle/presentation/maintenance/MaintenanceDialog.kt
🧰 Additional context used
🧬 Code graph analysis (1)
presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt (2)
presentation/src/main/java/com/puzzle/presentation/maintenance/MaintenanceDialog.kt (1)
  • MaintenanceDialog (20-55)
presentation/src/main/java/com/puzzle/presentation/update/ForceUpdateDialog.kt (1)
  • ForceUpdateDialog (25-61)
⏰ 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: build
🔇 Additional comments (1)
presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt (1)

40-43: LGTM on imports and parameter addition.

The new imports and nullable parameter correctly support the maintenance period feature.

Also applies to: 54-54

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
presentation/src/main/java/com/puzzle/presentation/update/ForceUpdateDialog.kt (1)

51-59: Avoid force unwrap on versionName which can be null.

PackageInfo.versionName can be null according to Android documentation (e.g., if not set in the manifest). Using !! could cause a crash in edge cases.

🛡️ Suggested defensive handling
 internal fun isShowForceUpdateDialog(
     context: Context,
     info: ForceUpdate?,
 ): Boolean {
     if (info == null) return false
 
-    val currentVersion = context.packageManager.getPackageInfo(context.packageName, 0).versionName
-    return checkShouldUpdate(currentVersion!!, info.minVersion)
+    val currentVersion = context.packageManager.getPackageInfo(context.packageName, 0).versionName
+        ?: return false
+    return checkShouldUpdate(currentVersion, info.minVersion)
 }
🧹 Nitpick comments (1)
presentation/src/main/java/com/puzzle/presentation/update/ForceUpdateDialog.kt (1)

81-83: Minor: consider handling single-part versions.

The function normalizes 2-part versions (e.g., "1.0"[1, 0, 0]) but leaves 1-part versions as-is (e.g., "1"[1]). While checkShouldUpdate handles this via getOrElse, you might want to normalize all short versions for consistency.

♻️ Optional: normalize all short versions
-private fun normalizeVersion(version: String): List<Int> = version.split('.')
-    .map { it.toIntOrNull() ?: 0 }
-    .let { if (it.size == 2) it + 0 else it }
+private fun normalizeVersion(version: String): List<Int> = version.split('.')
+    .map { it.toIntOrNull() ?: 0 }
+    .let { parts -> parts + List(maxOf(0, 3 - parts.size)) { 0 } }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 48e3a50 and 3f83991.

📒 Files selected for processing (2)
  • presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt
  • presentation/src/main/java/com/puzzle/presentation/update/ForceUpdateDialog.kt
🧰 Additional context used
🧬 Code graph analysis (2)
presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt (2)
presentation/src/main/java/com/puzzle/presentation/update/ForceUpdateDialog.kt (2)
  • isShowForceUpdateDialog (51-59)
  • ForceUpdateDialog (20-49)
presentation/src/main/java/com/puzzle/presentation/maintenance/MaintenanceDialog.kt (1)
  • MaintenanceDialog (20-55)
presentation/src/main/java/com/puzzle/presentation/update/ForceUpdateDialog.kt (2)
core/designsystem/src/main/java/com/puzzle/designsystem/component/Dialog.kt (1)
  • PieceDialog (33-58)
core/designsystem/src/main/java/com/puzzle/designsystem/component/Button.kt (1)
  • PieceSolidButton (44-72)
⏰ 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: build
🔇 Additional comments (4)
presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt (3)

65-69: State derivation logic looks correct and addresses previous null safety concerns.

The takeIf { it.isNotBlank() } pattern correctly handles the nullable chain, and the prioritization logic (maintenance takes precedence over force update) is properly implemented.

Minor performance consideration: isShowForceUpdateDialog(context, forceUpdate) calls PackageManager.getPackageInfo() on each recomposition. This is unlikely to cause issues in practice, but you could wrap it in remember(forceUpdate) if recomposition frequency becomes a concern.


74-74: LGTM!

The blur modifier is correctly applied to the Scaffold when either popup is showing, providing consistent visual feedback.


129-134: LGTM! Dialog precedence is correctly implemented.

The conditional rendering ensures mutual exclusivity between MaintenanceDialog and ForceUpdateDialog, with maintenance taking priority. This addresses the previously raised concerns about:

  1. Both dialogs showing simultaneously (now impossible due to else if)
  2. Null safety (resolved by extracting maintenanceString earlier)
presentation/src/main/java/com/puzzle/presentation/update/ForceUpdateDialog.kt (1)

20-49: LGTM!

The refactored ForceUpdateDialog cleanly delegates visibility control to the caller, making the component simpler and more reusable. The empty onDismissRequest is appropriate for a force update scenario where the user must take action.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@comst19 comst19 requested a review from kkh725 January 15, 2026 11:00
Copy link
Collaborator

@kkh725 kkh725 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다!

}

override suspend fun getMaintenancePeriod(): MaintenancePeriod {
return configureDataSource.getReferenceType(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

한줄리턴이면 그냥 = 쓰는방향으로 가면 좋을듯합니다

override fun onUpdate(configUpdate: ConfigUpdate) {
remoteConfig.activate()
}
override fun onError(error: FirebaseRemoteConfigException) {}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기 로깅이라도 남겨주는게 좋을듯??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ㅁㅅ민수 리뷰 원해요🔥 피어의 리뷰를 기다리는 ing.. 🔥

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants