Skip to content

๐Ÿ”€ :: (#798) ๊ทธ๋ž˜๋“ค ๋ฒ„์ „ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ - #799

Merged
uson1004 merged 14 commits into
developfrom
refactor/798-๊ทธ๋ž˜๋“ค-๋ฒ„์ „-๋งˆ์ด๊ทธ๋ ˆ์ด์…˜
Nov 27, 2025

Hidden character warning

The head ref may contain hidden characters: "refactor/798-\uadf8\ub798\ub4e4-\ubc84\uc804-\ub9c8\uc774\uadf8\ub808\uc774\uc158"
Merged

๐Ÿ”€ :: (#798) ๊ทธ๋ž˜๋“ค ๋ฒ„์ „ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜#799
uson1004 merged 14 commits into
developfrom
refactor/798-๊ทธ๋ž˜๋“ค-๋ฒ„์ „-๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

Conversation

@uson1004

@uson1004 uson1004 commented Nov 27, 2025

Copy link
Copy Markdown
Member

๊ฐœ์š”

๋ฒ„์ „ ์—…๊ทธ๋ ˆ์ด๋“œ ๋ฐ ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์˜์กด์„ฑ ์ตœ์‹ ํ™”

์ž‘์—…์‚ฌํ•ญ

  • AGP 8.2.2 -> 8.9.1
  • kotlin 1.9.20 -> 2.0.0
  • compile sdk 34 -> 36
  • ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—…๊ทธ๋ ˆ์ด๋“œ

์ถ”๊ฐ€ ๋กœ ํ•  ๋ง

Summary by CodeRabbit

  • Chores

    • Upgraded Gradle/Kotlin/AGP/Compose tooling, bumped compile/target SDK to 36, and upgraded Gradle wrapper.
  • New Features

    • Pull-to-refresh on Home now uses explicit refresh state with clear success/error toasts.
    • In-app updates now use a launcher-based flow for more reliable handling.
  • Style / UX

    • Switched to Material3 ripples and refined divider visuals for consistent UI.
    • Modal bottom sheets default behavior adjusted to avoid dismissing on back press.

โœ๏ธ Tip: You can customize this high-level summary in your review settings.

@uson1004
uson1004 requested a review from parkuiery November 27, 2025 01:14
@uson1004 uson1004 self-assigned this Nov 27, 2025
@uson1004 uson1004 added the setting ํ”„๋กœ์ ํŠธ์˜ ๊ธฐ๋ณธ์ ์ธ ์„ค์ •์„ ํ•  ๊ฒฝ์šฐ label Nov 27, 2025
@coderabbitai

coderabbitai Bot commented Nov 27, 2025

Copy link
Copy Markdown

Walkthrough

Upgrades Gradle, Kotlin, AGP, Compose and Compose compiler; adds compose compiler plugin across modules; removes androidx.window/accompanist adaptive and DisplayFeature usage; refactors HomeScreen pull-to-refresh to callback-driven isRefreshing; removes windowInsets from ModalBottomSheet API; UI tweaks (dividers, ripple) and minor formatting/import changes.

Changes

Cohort / File(s) Summary
Build system & versions
gradle/libs.versions.toml, gradle/wrapper/gradle-wrapper.properties, buildSrc/src/main/kotlin/ProjectProperties.kt
Upgraded version catalog and Gradle wrapper (Gradle โ†’ 8.11.1); bumped Kotlin/AGP/Compose versions; added composeCompiler entry; COMPILE_SDK and TARGET_SDK bumped 34โ†’36.
Compose compiler plugin adoption
app/build.gradle.kts, core/design-system/build.gradle.kts, core/ui/build.gradle.kts, core/widget/build.gradle.kts, feature/build.gradle.kts
Added alias(libs.plugins.compose.compiler) to plugins blocks and removed explicit composeOptions { kotlinCompilerExtensionVersion = ... }.
Adaptive layout / DisplayFeature removal & MainActivity updates
app/src/main/java/.../DmsApp.kt, app/src/main/java/.../MainActivity.kt, app/build.gradle.kts
Dropped DisplayFeature parameter and related import; removed androidx.window/accompanist.adaptive usages; MainActivity switched to launcher-based inโ€‘app update flow using ActivityResultContracts/StartIntentSenderForResult and AppUpdateOptions.
Pull-to-refresh refactor (HomeScreen)
feature/src/main/java/.../feature/main/home/HomeScreen.kt
Replaced PullToRefreshContainer with PullToRefreshBox; introduced isRefreshing state and onRefresh callback; moved refresh handling to callback and adjusted side-effect handling (success/error toggles).
Design system UI / API changes
core/design-system/src/main/java/.../Clickable.kt, core/design-system/src/main/java/.../Modal.kt, core/design-system/src/main/java/.../Buttons.kt
Switched to Material3 ripple API and made ripple conditional; removed windowInsets parameter from ModalBottomSheet API and changed default properties; replaced Divider with HorizontalDivider and explicit thickness/color usage.
UI import, minor behavior-preserving edits & formatting
core/ui/src/main/java/.../CollectInLaunchedEffectWithLifecycle.kt, feature/src/main/java/.../application/ApplicationScreen.kt, feature/.../MyPageScreen.kt, feature/.../NoticeDetailsScreen.kt, feature/.../OutingApplicationScreen.kt, feature/.../VotingSelectedScreen.kt, data/.../voting/*, app/.../navigation/*, others
Reordered/changed imports (e.g., LocalLifecycleOwner โ†’ androidx.lifecycle.compose.LocalLifecycleOwner), swapped dividers to HorizontalDivider, adjusted menuAnchor usage, small trailing-comma/formatting edits, and import-only reorganizations.
Gradle / toolchain tweaks
shared/validator/build.gradle.kts
Added kotlin { jvmToolchain(17) } JVM toolchain configuration.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor User
    participant HomeScreen
    participant ViewModel
    participant Network
    Note over HomeScreen: Pull-to-refresh (callback-based)
    User->>HomeScreen: Pull gesture
    HomeScreen->>HomeScreen: set isRefreshing = true
    HomeScreen->>ViewModel: onRefresh() (UpdateMeal intent)
    ViewModel->>Network: request meal update
    Network-->>ViewModel: MealUpdated / Error
    ViewModel-->>HomeScreen: emit state/side-effect
    HomeScreen->>HomeScreen: set isRefreshing = false
    HomeScreen->>User: show success or error toast
Loading
sequenceDiagram
    autonumber
    participant MainActivity
    participant PlayCore
    participant System
    Note over MainActivity: In-app update via launcher
    MainActivity->>PlayCore: build AppUpdateOptions(IMMEDIATE)
    MainActivity->>System: startIntentSenderForResult via updateLauncher
    System-->>MainActivity: onActivityResult (update result)
    MainActivity->>PlayCore: handle result (complete / retry / error)
Loading

Estimated code review effort

๐ŸŽฏ 3 (Moderate) | โฑ๏ธ ~30 minutes

  • Areas to focus:
    • HomeScreen pull-to-refresh state transitions and side-effect handling.
    • MainActivity in-app update launcher usage and result handling.
    • Cross-module build changes: Compose compiler plugin adoption and SDK/tooling bumps (Kotlin/AGP/Compose) for compatibility issues.

Possibly related PRs

Suggested reviewers

  • parkuiery

Poem

๐Ÿฐ Hopping through code with a curious twitch,
Toolchains refreshed, dependencies stitched,
Ripples now gentle, modals trimmed neat,
Pull-to-refresh hums a rhythmic beat,
The rabbit applauds โ€” a tidy commit! ๐Ÿฅ•

Pre-merge checks and finishing touches

โŒ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage โš ๏ธ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check โ“ Inconclusive The title is vague and uses non-descriptive terms like emoji and Korean text without clear context about the main change being Gradle version migration. Consider using a clearer English title such as 'Upgrade Gradle and dependencies to latest versions' or 'Migrate to Gradle 8.9.1, Kotlin 2.0.0, and compileSdk 36' for better clarity.
โœ… Passed checks (1 passed)
Check name Status Explanation
Description Check โœ… Passed Check skipped - CodeRabbitโ€™s high-level summary is enabled.
โœจ Finishing touches
  • ๐Ÿ“ Generate docstrings
๐Ÿงช Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/798-๊ทธ๋ž˜๋“ค-๋ฒ„์ „-๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

๐Ÿ“œ Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between 2d76a02 and c07ce0a.

๐Ÿ“’ Files selected for processing (10)
  • app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt (1 hunks)
  • app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavGraph.kt (1 hunks)
  • app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavigator.kt (1 hunks)
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Buttons.kt (5 hunks)
  • data/src/main/java/team/aliens/dms/android/data/voting/mapper/VotingMapper.kt (1 hunks)
  • data/src/main/java/team/aliens/dms/android/data/voting/repository/VotingRepository.kt (1 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt (2 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/notice/NoticeDetailsScreen.kt (2 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt (1 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/voting/VotingSelectedScreen.kt (1 hunks)
โœ… Files skipped from review due to trivial changes (3)
  • app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt
  • data/src/main/java/team/aliens/dms/android/data/voting/repository/VotingRepository.kt
  • data/src/main/java/team/aliens/dms/android/data/voting/mapper/VotingMapper.kt
๐Ÿšง Files skipped from review as they are similar to previous changes (3)
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Buttons.kt
  • feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt
  • feature/src/main/java/team/aliens/dms/android/feature/notice/NoticeDetailsScreen.kt
๐Ÿ”‡ Additional comments (4)
feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt (1)

23-25: HorizontalDivider migration and DividerDefaults usage look correct

The switch to HorizontalDivider with DividerDefaults.Thickness and the explicit line color is consistent with the Material3 API and should preserve/clarify the previous visual behavior. Layout modifiers (fillMaxWidth().horizontalPadding()) match the expected full-width divider pattern within the card.

No functional issues from this change; just ensure your Material3 version in this Gradle/Kotlin upgrade indeed exposes HorizontalDivider and DividerDefaults.Thickness as used here (it should, given recent versions).

Also applies to: 535-540

feature/src/main/java/team/aliens/dms/android/feature/voting/VotingSelectedScreen.kt (1)

30-63: Import cleanup LGTM; no behavior change

LocalContext is now imported once and still used correctly for toast string lookup; this is a pure import reโ€‘org with no impact on runtime behavior.

Please make sure the module still builds and runs under the new Kotlin/AGP/compileSdk versions as part of your overall PR verification.

app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavGraph.kt (1)

17-37: Imports remain consistent with navigation graph usage

VolunteersScreenDestination and VotingNavGraph imports line up with their usages in destinationsByRoute and nestedNavGraphs; no behavioral change and the authorized graph wiring stays coherent.

app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavigator.kt (1)

14-28: AuthorizedNavigator now contracts voting navigation as well

By extending VotingNavigator, any AuthorizedNavigator implementation must also provide voting navigation behavior. This looks consistent with the authorized graph containing voting destinations, but it does change the interface contractโ€”please confirm all existing implementers have been updated or delegate to a shared VotingNavigator implementation as needed.


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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

๐Ÿงน Nitpick comments (4)
core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Clickable.kt (1)

5-6: Material3 ripple usage is correct; consider avoiding work when ripple == false

The migration to material3.ripple and passing it as an indication is fine. Right now, ripple(...) is evaluated even when the ripple flag is false due to .takeIf { ripple }. If you care about avoiding that extra work and making intent clearer, you could switch to:

indication = if (ripple) {
    ripple(
        color = rippleColor ?: DmsTheme.colorScheme.surfaceVariant,
        radius = rippleRadius ?: Dp.Unspecified,
    )
} else {
    null
}

This keeps behavior the same while skipping ripple creation when disabled.

Also applies to: 26-31

app/build.gradle.kts (1)

38-43: Minor: remove duplicate aaptOptions.cruncherEnabled = false in debug buildType

aaptOptions.cruncherEnabled = false is set twice in the debug block. Itโ€™s harmless but redundant; you can drop one of them to keep the config clean.

core/ui/build.gradle.kts (1)

58-63: Consider moving Compose test JUnit to the test configuration

implementation(libs.androidx.compose.test.junit) is currently in the main implementation configuration. Itโ€™s usually intended only for tests and can be moved to androidTestImplementation (or testImplementation as appropriate) to avoid shipping test-only code in the main artifact.

app/src/main/java/team/aliens/dms/android/app/MainActivity.kt (1)

41-51: Adaptive layout TODO is a good placeholder; consider linking a tracking item

Leaving the TODO above windowSizeClass keeps the intent clear after removing the previous adaptive layout code. If you have a tracking issue (e.g., GitHub/Jira ID), consider referencing it in the comment so itโ€™s easier to discover later.

๐Ÿ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between 74d41a6 and 9b55e60.

๐Ÿ“’ Files selected for processing (13)
  • app/build.gradle.kts (1 hunks)
  • app/src/main/java/team/aliens/dms/android/app/DmsApp.kt (0 hunks)
  • app/src/main/java/team/aliens/dms/android/app/MainActivity.kt (1 hunks)
  • buildSrc/src/main/kotlin/ProjectProperties.kt (1 hunks)
  • core/design-system/build.gradle.kts (1 hunks)
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Clickable.kt (2 hunks)
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Modal.kt (0 hunks)
  • core/ui/build.gradle.kts (1 hunks)
  • core/widget/build.gradle.kts (1 hunks)
  • feature/build.gradle.kts (1 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt (4 hunks)
  • gradle/libs.versions.toml (3 hunks)
  • gradle/wrapper/gradle-wrapper.properties (1 hunks)
๐Ÿ’ค Files with no reviewable changes (2)
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Modal.kt
  • app/src/main/java/team/aliens/dms/android/app/DmsApp.kt
๐Ÿงฐ Additional context used
๐Ÿงฌ Code graph analysis (1)
app/src/main/java/team/aliens/dms/android/app/MainActivity.kt (2)
core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Theme.kt (1)
  • DmsTheme (11-35)
app/src/main/java/team/aliens/dms/android/app/DmsApp.kt (1)
  • DmsApp (34-95)
๐Ÿ”‡ Additional comments (14)
feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt (4)

115-120: LGTM - Clean pull-to-refresh state management.

The callback-based pattern with explicit isRefreshing state aligns well with Material3's PullToRefreshBox API. The state is properly managed: set to true on refresh trigger and reset in side effect handlers.


122-138: LGTM - Comprehensive side effect handling.

All paths correctly reset isRefreshing to false, preventing the refresh indicator from getting stuck. Both success and error cases provide appropriate user feedback.


232-241: LGTM - MealCards integration and layout spacing.

The onRefresh callback is correctly wired to allow refresh from the empty state button within MealCard. The bottom spacer provides clearance for the bottom navigation bar.


188-194: PullToRefreshBox API is correct and compatible with Material3 1.3.2.

The implementation at lines 188-194 matches the Material3 1.3.2 API signature exactly:

  • state: PullToRefreshState โœ“
  • isRefreshing: Boolean โœ“
  • onRefresh: () -> Unit โœ“

All parameters are properly typed and ordered. No API compatibility issues found.

gradle/wrapper/gradle-wrapper.properties (1)

4-4: Gradle 8.11.1 bump looks consistent with the rest of the toolchain upgrades

The wrapper URL change is straightforward and aligns with the AGP/Kotlin/Compose bumps; just ensure CI and local environments are actually using this wrapper when running builds.

buildSrc/src/main/kotlin/ProjectProperties.kt (1)

2-4: SDK level bump to 36 is consistent with the migration

Raising both COMPILE_SDK and TARGET_SDK to 36 is aligned with the Gradle/Kotlin/Compose upgrades and centralizes the config cleanly in ProjectProperties.

core/widget/build.gradle.kts (1)

1-9: Compose compiler plugin addition fits the new toolchain

Adding libs.plugins.compose.compiler here is consistent with other modules and with the Kotlin 2.0/AGP 8.x migration, especially since buildFeatures.compose = true is enabled.

app/build.gradle.kts (1)

4-13: App module now correctly opts into the Compose compiler plugin

Adding compose.compiler to the application module keeps it in sync with the library modules and is required for the upgraded Kotlin/Compose stack.

feature/build.gradle.kts (1)

4-11: Feature module Compose compiler plugin usage is consistent with other modules

Enabling libs.plugins.compose.compiler here matches the pattern in app/core modules and is appropriate since this module is Compose-heavy.

core/ui/build.gradle.kts (1)

4-9: Compose compiler plugin is correctly added to the core UI module

Adding the Compose compiler plugin here aligns this module with the rest of the Compose stack and the Kotlin 2.0 upgrade.

core/design-system/build.gradle.kts (1)

9-9: Compose compiler plugin adoption aligns with Kotlin 2.0.0 best practices.

Adding the Compose compiler plugin and removing the deprecated composeOptions block is the correct approach for Kotlin 2.0.0 and Compose 1.7.8.

Please verify cross-module consistency by confirming that all modules (e.g., feature, app, core/ui/widget) adopt the same Compose compiler plugin pattern, and run your test suite to ensure Kotlin 2.0.0 and Compose 1.7.8 compatibility.

gradle/libs.versions.toml (3)

50-50: Compose compiler plugin version alignment is correct.

The new composeCompiler version (2.0.0, line 50) and compose-compiler plugin (line 122) both correctly reference kotlinJvm (2.0.0), ensuring version alignment.

Also applies to: 122-122


1-122: Removal of androidx-window is applied consistently across the codebase.

Verification confirms no remaining references to androidx-window exist in any build.gradle.kts files, gradle files, or source code imports. The removal from the version catalog is complete and consistent.


24-24: Verify Kotlin 2.0.0 breaking changes and KSP processor compatibility; major versions are officially supported.

Kotlin 2.0.0 is compatible with AGP 8.9.1 (requires AGP 8.5+), Compose 1.7.8 officially supports Kotlin 2.0.0 with the new compose-compiler plugin (correctly added in the PR), and Hilt 2.51.1 is compatible with both. KSP 2.0.0-1.0.24 is officially supported by Kotlin 2.0.0 (K2 compiler).

However, Kotlin 2.0.0 introduced breaking changes (invokedynamic lambda defaults, type-resolution changes, warnings elevated to errors, and stricter overload resolution). Additionally, KSP processors (including compose-destinations-ksp used in this codebase) must be K2/KSP2-compatible.

Verify:

  1. Kotlin 2.0.0 breaking changes do not impact the codebase (review Compatibility guide for Kotlin 2.0.x for breaking patterns like conflicting inherited members, overload priority changes, and type approximation differences).
  2. The compose-destinations library version used is K2/KSP2-compatible (check its release notes or bump to a version explicitly supporting Kotlin 2.0.0 if needed).

Comment on lines +203 to +211
if (uiState.newNoticesExist) {
AnnouncementCard(
modifier = Modifier.fillMaxWidth(),
visible = true,
onNavigateToAnnouncementList = onNavigateToAnnouncementList,
)
} else {
Spacer(modifier = Modifier.height(DefaultHomeScreenVerticalSpace))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸก Minor

Exit animation will not play due to conditional composition.

The AnnouncementCard is conditionally composed only when newNoticesExist is true. When it becomes false, the component is removed from composition entirely and replaced with a Spacer, so the exit animation (slideOutVertically + fadeOut) defined in AnnouncementCard will never run.

To preserve the exit animation:

-                if (uiState.newNoticesExist) {
-                    AnnouncementCard(
-                        modifier = Modifier.fillMaxWidth(),
-                        visible = true,
-                        onNavigateToAnnouncementList = onNavigateToAnnouncementList,
-                    )
-                } else {
-                    Spacer(modifier = Modifier.height(DefaultHomeScreenVerticalSpace))
-                }
+                AnnouncementCard(
+                    modifier = Modifier.fillMaxWidth(),
+                    visible = uiState.newNoticesExist,
+                    onNavigateToAnnouncementList = onNavigateToAnnouncementList,
+                )
+                if (!uiState.newNoticesExist) {
+                    Spacer(modifier = Modifier.height(DefaultHomeScreenVerticalSpace))
+                }

Alternatively, if exit animation is not needed, you can remove AnimatedVisibility from AnnouncementCard and simplify it.

๐Ÿ“ Committable suggestion

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (uiState.newNoticesExist) {
AnnouncementCard(
modifier = Modifier.fillMaxWidth(),
visible = true,
onNavigateToAnnouncementList = onNavigateToAnnouncementList,
)
} else {
Spacer(modifier = Modifier.height(DefaultHomeScreenVerticalSpace))
}
AnnouncementCard(
modifier = Modifier.fillMaxWidth(),
visible = uiState.newNoticesExist,
onNavigateToAnnouncementList = onNavigateToAnnouncementList,
)
if (!uiState.newNoticesExist) {
Spacer(modifier = Modifier.height(DefaultHomeScreenVerticalSpace))
}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

โš ๏ธ Outside diff range comments (1)
app/src/main/java/team/aliens/dms/android/app/MainActivity.kt (1)

68-84: Based on my verification through the Play Core library documentation and codebase inspection:

The review comment is accurate and well-founded. The Play Core library documentation explicitly requires checking updateAvailability() and isUpdateTypeAllowed() before calling startUpdateFlowForResult(). The current implementation at lines 72-83 unconditionally invokes the update flow without these required precondition checks, which violates documented API requirements and can cause unexpected behavior when no update is available.

Update availability check and error handling are missing and must be added.

The code at lines 72โ€“83 calls startUpdateFlowForResult without verifying:

  1. appUpdateInfo.updateAvailability() == UPDATE_AVAILABLE (or DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS for resumed updates)
  2. appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
  3. Any error handling via addOnFailureListener

Per Play Core library documentation, apply the suggested checks:

         appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
+            if (appUpdateInfo.updateAvailability() == com.google.android.play.core.install.model.UpdateAvailability.UPDATE_AVAILABLE &&
+                appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
+            ) {
                 val updateOptions = AppUpdateOptions
                     .newBuilder(AppUpdateType.IMMEDIATE)
                     .setAllowAssetPackDeletion(true)
                     .build()

                 appUpdateManager.startUpdateFlowForResult(
                     appUpdateInfo,
                     updateLauncher,
                     updateOptions,
                 )
+            }
         }

Also add error handling:

appUpdateInfoTask.addOnFailureListener { exception ->
    // Log or handle the failure to fetch update info
}
๐Ÿงน Nitpick comments (4)
gradle/libs.versions.toml (1)

49-49: Clarify compose-compiler version reference.

Line 121 defines the compose-compiler plugin using version.ref = "kotlinJvm" (which resolves to 2.0.0), but a dedicated composeCompiler version exists at line 49 (also 2.0.0). While both reference the same version currently, using version.ref = "composeCompiler" would improve clarity and reduce maintenance risk if the versions ever need to diverge.

- compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlinJvm" }
+ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "composeCompiler" }

Also applies to: 121-121

feature/src/main/java/team/aliens/dms/android/feature/notice/NoticeDetailsScreen.kt (1)

102-107: HorizontalDivider usage is correct; consider a shared wrapper if reused

Using HorizontalDivider with DividerDefaults.Thickness and DmsTheme.colorScheme.line keeps behavior and theming clear and explicit. If this exact divider style is reused across multiple screens (as it seems from the PR scope), consider extracting a small DmsHorizontalDivider in the design system to centralize thickness/color and avoid repetition.

feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt (1)

40-81: LocalLifecycleOwner import is correct; consider moving lifecycle observation into DisposableEffect

Switching to androidx.lifecycle.compose.LocalLifecycleOwner is consistent with collectAsStateWithLifecycle and keeps all lifecycleโ€‘compose usage in one place, so this import change looks good.

Given the ongoing lifecycle/Compose upgrades, this is also a good moment to avoid doing LocalLifecycleOwner.current.lifecycle.addObserver(viewModel) directly in the composable body, since it will be executed on every recomposition. A cleaner pattern is to register/unregister once with DisposableEffect:

@@
-    val viewModel: ApplicationViewModel = hiltViewModel()
-    val uiState by viewModel.stateFlow.collectAsStateWithLifecycle()
-    var selectedTab by remember { mutableIntStateOf(0) }
-    val tabs = listOf("์‹ ์ฒญ", "ํˆฌํ‘œ")
-
-    LocalLifecycleOwner.current.lifecycle.addObserver(viewModel)
+    val viewModel: ApplicationViewModel = hiltViewModel()
+    val uiState by viewModel.stateFlow.collectAsStateWithLifecycle()
+    var selectedTab by remember { mutableIntStateOf(0) }
+    val tabs = listOf("์‹ ์ฒญ", "ํˆฌํ‘œ")
+
+    val lifecycleOwner = LocalLifecycleOwner.current
+    DisposableEffect(lifecycleOwner, viewModel) {
+        lifecycleOwner.lifecycle.addObserver(viewModel)
+        onDispose {
+            lifecycleOwner.lifecycle.removeObserver(viewModel)
+        }
+    }

(Remember to add import androidx.compose.runtime.DisposableEffect if you apply this.)

app/src/main/java/team/aliens/dms/android/app/MainActivity.kt (1)

33-39: Consider implementing the forced update modal or tracking this TODO.

For IMMEDIATE updates, unhandled cancellation leaves the app in an inconsistent state. The user can continue using an outdated version, which may defeat the purpose of forcing an immediate update.

Would you like me to open an issue to track the implementation of the forced update modal, or generate a basic implementation that re-triggers the update flow on cancellation?

๐Ÿ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between 9b55e60 and 6b9b66c.

๐Ÿ“’ Files selected for processing (14)
  • app/src/main/java/team/aliens/dms/android/app/MainActivity.kt (4 hunks)
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Buttons.kt (5 hunks)
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Modal.kt (1 hunks)
  • core/ui/src/main/java/team/aliens/dms/android/core/ui/CollectInLaunchedEffectWithLifecycle.kt (1 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt (2 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt (3 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt (2 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/notice/NoticeDetailsScreen.kt (2 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt (4 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt (1 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/resetpassword/AccountVerificationScreen.kt (2 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/resetpassword/ResetPasswordViewModel.kt (2 hunks)
  • gradle/libs.versions.toml (3 hunks)
  • shared/validator/build.gradle.kts (1 hunks)
โœ… Files skipped from review due to trivial changes (2)
  • feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt
  • feature/src/main/java/team/aliens/dms/android/feature/resetpassword/ResetPasswordViewModel.kt
๐Ÿšง Files skipped from review as they are similar to previous changes (2)
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Modal.kt
  • feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt
๐Ÿ”‡ Additional comments (11)
feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt (1)

23-25: HorizontalDivider + DividerDefaults usage looks correct

Switching to HorizontalDivider and DividerDefaults.Thickness keeps behavior aligned with Material3โ€™s current API and preserves your existing custom line color. No functional issues spotted in the updated option divider block.

Please run the module build / UI tests after the Gradle & Compose upgrade to confirm there are no breaking API changes around HorizontalDivider or DividerDefaults in your exact Compose version.

Also applies to: 535-540

feature/src/main/java/team/aliens/dms/android/feature/resetpassword/AccountVerificationScreen.kt (2)

65-81: Side-effect handling remains correct; trailing comma is fine

The InvalidEmailFormat branch still correctly shows the toast with the expected string; adding the trailing comma is purely formatting and has no behavioral impact. All good here.


158-171: TextField keyboardOptions unchanged in behavior

keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next,) is equivalent to the previous form; the trailing comma is valid Kotlin and doesnโ€™t alter runtime behavior. This keeps the multi-line call consistent and is fine as-is.

core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Buttons.kt (2)

18-19: LGTM! Correct imports for Compose Material3 API migration.

The new imports support the migration from deprecated Divider to HorizontalDivider, aligning with Material3 best practices.


597-602: LGTM! Consistent API migration from deprecated Divider.

All four divider instances in the preview function have been correctly migrated to HorizontalDivider with explicit styling parameters, ensuring visual consistency and compatibility with the updated Compose Material3 APIs.

Also applies to: 671-676, 745-750, 842-847

shared/validator/build.gradle.kts (1)

12-14: โœ“ JVM toolchain alignment is correct.

The addition of jvmToolchain(17) establishes consistency across modules and aligns with Kotlin 2.0.0 requirements. This configuration pairs well with the java = "17" version in libs.versions.toml.

gradle/libs.versions.toml (1)

19-49: Major version upgrades are well-coordinated but require verification.

Kotlin 2.0.0 is fully compatible with Gradle 6.8.3 through 8.5, and the Gradle 8.9.1 upgrade is within a reasonable range. When upgrading to Kotlin 2.0.0, KSP libraries and Android Gradle Plugin versions must also be updated, which is done here correctly (AGP 8.9.1, KSP 2.0.0-1.0.24). For Kotlin 2.0 or higher, configure Compose using the Compose Compiler Gradle plugin, and when using it, you don't have to check Compose to Kotlin compatibility.

However, verify that all modules using Compose have migrated to use the Compose Compiler Gradle plugin and have removed explicit kotlinCompilerExtensionVersion configurations, as this PR summary mentions that adoption is in progress.

core/ui/src/main/java/team/aliens/dms/android/core/ui/CollectInLaunchedEffectWithLifecycle.kt (1)

9-9: LocalLifecycleOwner import migration matches lifecycleโ€‘compose and keeps behavior unchanged

Switching to androidx.lifecycle.compose.LocalLifecycleOwner is the correct migration for newer Compose/lifecycle artifacts and preserves the existing behavior of collectInLaunchedEffectWithLifecycle, since the default lifecycle still comes from LocalLifecycleOwner.current.lifecycle. Please just confirm that the corresponding lifecycle-runtime-compose (or equivalent) dependency is present and on a version compatible with your upgraded AGP/Kotlin/Compose stack.

feature/src/main/java/team/aliens/dms/android/feature/notice/NoticeDetailsScreen.kt (1)

11-13: Imports align with Material3 divider migration

The added imports cleanly support the new divider implementation below and are consistent with the Material3 HorizontalDivider/DividerDefaults pattern.

feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt (1)

150-155: Trailing comma on remainsOptionTitle argument is fine

The added trailing comma on remainsOptionTitle = uiState.appliedRemainsOption?.title, is idiomatic Kotlin for multiโ€‘line calls and has no behavioral impact. It improves future diffs and formatting.

feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt (1)

29-29: LGTM!

Import required for the updated menuAnchor API.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 0

๐Ÿงน Nitpick comments (1)
core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Modal.kt (1)

29-31: Default now blocks backโ€‘press dismissal for all sheets using this wrapper

Changing the default from the libraryโ€™s ModalBottomSheetDefaults.properties to ModalBottomSheetProperties(shouldDismissOnBackPress = false) means every ModalBottomSheet that relies on the default will no longer dismiss on system back. Thatโ€™s a fairly visible global behavior change.

If this was only meant to fix the deprecation/ABI change around ModalBottomSheetDefaults.properties, consider either:

  • keeping the previous behavior via properties: ModalBottomSheetProperties = ModalBottomSheetDefaults.properties, or
  • overriding properties at specific call sites that must not be dismissible, instead of changing the designโ€‘system default.

Please doubleโ€‘check that all affected screens are expected to ignore backโ€‘press for sheet dismissal.

๐Ÿ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between 6b9b66c and 2d76a02.

๐Ÿ“’ Files selected for processing (2)
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Modal.kt (1 hunks)
  • feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt (4 hunks)
๐Ÿšง Files skipped from review as they are similar to previous changes (1)
  • feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt

@uson1004
uson1004 merged commit ebfff20 into develop Nov 27, 2025
1 check passed
@uson1004
uson1004 deleted the refactor/798-๊ทธ๋ž˜๋“ค-๋ฒ„์ „-๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ branch November 27, 2025 07:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

setting ํ”„๋กœ์ ํŠธ์˜ ๊ธฐ๋ณธ์ ์ธ ์„ค์ •์„ ํ•  ๊ฒฝ์šฐ

Projects

None yet

Development

Successfully merging this pull request may close these issues.

๊ทธ๋ž˜๋“ค ๋ฒ„์ „ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

1 participant