Skip to content

Conversation

@kartikey004
Copy link
Contributor

@kartikey004 kartikey004 commented Dec 31, 2025

Fixes - Jira-#620

Fixed the "Server Config" button so it correctly opens the screen and updated the design to make switching between Local and Demo environments easier.

Added a popup window with a countdown and a "Restart Now" button to clearly show that changes are saved before the app restarts.

Screenshots:
Screenshot_20251227_172730 Screenshot_20260101_154344 Screenshot_20260101_155214

Summary by CodeRabbit

  • New Features

    • New navigation path to the server configuration screen with back-navigation support.
    • Centered restart countdown dialog that confirms saved changes and can restart immediately.
    • Quick Setup options added (Local / Demo) and an "OR" divider in settings.
  • Improvements

    • Added user-facing messages: "Configuration Saved" and "Restarting application to apply changes."
    • Settings UI spacing, labels, and styling refined for improved clarity and visual consistency.

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

@coderabbitai
Copy link

coderabbitai bot commented Dec 31, 2025

📝 Walkthrough

Walkthrough

Added two navigation helpers and a server-config navigation graph; wired settings to open the server-config screen. Replaced a bottom snackbar with a centered RestartCountdownDialog after saving configuration, including an immediate "Restart Now" action and auto-restart on dismiss.

Changes

Cohort / File(s) Summary
Navigation additions
cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt
Added navigateToServerConfigGraph and serverConfigGraph; settingsScreen now calls navigateToServerConfigGraph; serverConfigGraph uses navController::popBackStack for navigateBack.
Settings string resources
feature/settings/src/commonMain/composeResources/values/feature_settings_.xml
Added string resources: feature_settings_restart_now, feature_settings_local, feature_settings_development, feature_settings_demo, feature_settings_or, feature_settings_environment, feature_settings_quick_setup, feature_settings_configuration_saved, feature_settings_restart_application.
Server config UI / dialog
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt
Replaced bottom SimpleCountdownSnackbar with centered RestartCountdownDialog (Card, CircularProgressIndicator, numeric countdown, success icon, "Restart Now" action); added overlay that consumes clicks; moved styling and strings to design tokens and string resources; added Quick Setup options and UI refinements.

Sequence Diagram

sequenceDiagram
    actor User
    participant SettingsUI as "Settings UI"
    participant Navigation as "Navigation"
    participant ServerConfig as "ServerConfig Screen"
    participant RestartDialog as "Restart Dialog"
    participant App as "App"

    User->>SettingsUI: Click "Update Configuration"
    SettingsUI->>Navigation: navigateToServerConfigGraph()
    Navigation->>ServerConfig: navigate to server config screen
    ServerConfig->>ServerConfig: save config
    ServerConfig->>RestartDialog: show RestartCountdownDialog on success

    rect rgb(230,245,255)
        Note over RestartDialog: Countdown phase (progress + numeric timer)
        RestartDialog->>User: show check icon, message, timer
    end

    alt User taps "Restart Now"
        User->>RestartDialog: Tap "Restart Now"
        RestartDialog->>App: trigger immediate restart
    else Countdown ends or dialog dismissed
        RestartDialog->>App: onDismiss triggers restart
    end

    App->>App: restart with new config
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped into settings, nimble and bright,
A dialog that glows in soft lunar light.
The timer spun numbers, a tiny delight,
"Restart Now" winked — I pushed with a paw,
Off we go restarting, tidy and raw.

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: fixing the Server Config button navigation and improving the UpdateServerConfigScreen design with new UI elements and styling.
✨ 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: 1

🧹 Nitpick comments (2)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt (2)

526-529: Consider removing the leading spaces.

The two leading spaces in the button text are unusual. If spacing is needed, prefer using padding modifiers on the Text composable instead.

🔎 Proposed refactor
-                    Text(
-                        "  " +
-                                stringResource(
-                                    Res.string.feature_settings_update_config_btn_text,
-                                ).uppercase(),
-                        fontFamily = FontFamily.SansSerif,
-                    )
+                    Text(
+                        stringResource(
+                            Res.string.feature_settings_update_config_btn_text,
+                        ).uppercase(),
+                        fontFamily = FontFamily.SansSerif,
+                        modifier = Modifier.padding(start = 4.dp),
+                    )

624-633: Consider using a string resource for "Restart Now".

The button text "Restart Now" is hardcoded. For consistency and internationalization support, consider adding it as a string resource in feature_settings_.xml.

🔎 Proposed refactor

Add to feature_settings_.xml:

<string name="feature_settings_restart_now">Restart Now</string>

Then update the button:

-                Text("Restart Now")
+                Text(stringResource(Res.string.feature_settings_restart_now))
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6694744 and 1f30b03.

📒 Files selected for processing (3)
  • cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt
  • feature/settings/src/commonMain/composeResources/values/feature_settings_.xml
  • feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt
🧰 Additional context used
🧬 Code graph analysis (1)
cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt (1)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/navigation/SettingsNavigation.kt (1)
  • serverConfigGraph (45-53)
🪛 GitHub Actions: PR Checks
cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt

[error] 87-87: spotlessKotlinCheck failed: formatting violations detected in the file. Run './gradlew :cmp-navigation:spotlessApply' to fix.

🔇 Additional comments (9)
feature/settings/src/commonMain/composeResources/values/feature_settings_.xml (1)

28-30: LGTM!

The new string resources are well-named and support the updated restart countdown dialog flow.

cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt (2)

30-31: LGTM!

The imports are correctly added to support the server config navigation flow.


89-91: LGTM!

The server config graph is properly integrated with correct back navigation wiring.

feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt (6)

14-53: LGTM!

The new import additions support the RestartCountdownDialog implementation and are all utilized in the updated UI flow.


124-142: LGTM! Clean modal overlay implementation.

The semi-transparent overlay with click consumption prevents user interaction during the restart countdown, which is appropriate UX for this critical flow.


181-182: Nice UI refinement!

The increased padding and spacing improves visual clarity and breathing room in the settings layout.


224-224: Good simplification!

Removing the emoji unicode characters makes the button labels cleaner and more consistent across platforms.

Also applies to: 261-261


557-620: LGTM! Well-structured dialog UI.

The RestartCountdownDialog has a clean, centered layout with appropriate spacing, colors, and visual hierarchy. The success icon, title, message, and countdown are well-organized.


539-555: The current progress calculation is correct and follows the expected UX pattern for a countdown timer. The progress drains from full (1.0 when 5 seconds remain) to empty (0.0 when 0 seconds remain), which aligns with the numeric countdown display (5 → 4 → 3 → 2 → 1 → 0) and clearly communicates "remaining time." Inverting the calculation would show elapsed time instead, which would be counterintuitive for a restart countdown dialog.

Likely an incorrect or invalid review comment.

.background(Color(0xfff8f9fa).copy(alpha = .1f)),
contentPadding = PaddingValues(4.dp),
verticalArrangement = Arrangement.spacedBy(4.dp),
contentPadding = PaddingValues(6.dp),
Copy link
Contributor

Choose a reason for hiding this comment

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

here color and dp values are hardcoded

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

Caution

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

⚠️ Outside diff range comments (1)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt (1)

118-118: Potential NPE from force unwrap on nullable state.

Using !! on viewModel.state.value can throw a NullPointerException if the state is null. Consider using a safe approach such as providing a default value or handling the null case gracefully.

🔎 Proposed fix
-            serverConfig = viewModel.state.value!!,
+            serverConfig = viewModel.state.value ?: return,

Or collect the state safely:

val serverConfig by viewModel.state.collectAsStateWithLifecycle()
// Then use serverConfig with null check or provide default
♻️ Duplicate comments (3)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt (3)

130-138: Hardcoded color for overlay background.

Color.Black.copy(alpha = 0.6f) should use a theme-aware color from MaterialTheme.colorScheme (e.g., scrim) or define it in AppColors/DesignToken for consistency.

🔎 Proposed fix
             Box(
                 modifier = Modifier
                     .fillMaxSize()
-                    .background(Color.Black.copy(alpha = 0.6f))
+                    .background(MaterialTheme.colorScheme.scrim.copy(alpha = 0.6f))
                     .clickable(

287-302: Hardcoded divider color.

Color.LightGray should be replaced with a theme-aware color such as MaterialTheme.colorScheme.outlineVariant for consistency with the design system.

🔎 Proposed fix
                     HorizontalDivider(
                         modifier = Modifier.weight(1f),
-                        color = Color.LightGray,
+                        color = MaterialTheme.colorScheme.outlineVariant,
                     )
                     // ... Text ...
                     HorizontalDivider(
                         modifier = Modifier.weight(1f),
-                        color = Color.LightGray,
+                        color = MaterialTheme.colorScheme.outlineVariant,
                     )

601-606: Hardcoded Color.Gray for secondary text.

Replace with a theme-aware color like MaterialTheme.colorScheme.onSurfaceVariant for consistency with the design system.

🔎 Proposed fix
             Text(
                 text = stringResource(Res.string.feature_settings_restart_application),
                 style = MaterialTheme.typography.bodyMedium,
-                color = Color.Gray,
+                color = MaterialTheme.colorScheme.onSurfaceVariant,
                 textAlign = TextAlign.Center,
             )
🧹 Nitpick comments (1)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt (1)

531-538: Avoid hardcoded spaces in text content.

Prepending " " for visual spacing is fragile. Use Modifier.padding() on the Text or adjust the button's contentPadding instead.

🔎 Proposed fix
                     Text(
-                        "  " +
-                            stringResource(
-                                Res.string.feature_settings_update_config_btn_text,
-                            ).uppercase(),
+                        text = stringResource(Res.string.feature_settings_update_config_btn_text).uppercase(),
+                        modifier = Modifier.padding(start = DesignToken.padding.small),
                         fontFamily = FontFamily.SansSerif,
                     )
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c10e60e and a30dabf.

📒 Files selected for processing (2)
  • feature/settings/src/commonMain/composeResources/values/feature_settings_.xml
  • feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • feature/settings/src/commonMain/composeResources/values/feature_settings_.xml
🧰 Additional context used
🧬 Code graph analysis (1)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt (1)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigViewModel.kt (1)
  • onEvent (79-141)
⏰ 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: PR Checks / Static Analysis Check
🔇 Additional comments (4)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt (4)

186-198: LGTM!

Good use of DesignToken for padding and spacing, aligning with the design system.


207-278: LGTM!

The elevated buttons properly use DesignToken for sizing/shapes and MaterialTheme.colorScheme for colors, following the design system consistently.


545-641: Well-structured countdown dialog implementation.

The RestartCountdownDialog properly uses LaunchedEffect for countdown timing, rememberSaveable for state persistence across configuration changes, and consistent DesignToken styling. The progress indicator API usage is correct.


306-477: LGTM!

The form fields consistently use DesignToken for shapes and padding, and MaterialTheme.colorScheme for colors, providing a unified look.

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

Caution

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

⚠️ Outside diff range comments (1)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt (1)

117-117: Force unwrap on nullable state could cause NPE.

viewModel.state.value!! will crash if the state is null. Consider using a null-safe approach or ensuring the state is never null by initializing with a default value.

🔎 Proposed fix

Option 1: Use safe call with early return:

+    val serverConfigState = viewModel.state.value ?: return
+
     Box(modifier = Modifier.fillMaxSize()) {
         UpdateServerConfigScreenContent(
             modifier = modifier,
-            serverConfig = viewModel.state.value!!,
+            serverConfig = serverConfigState,

Option 2: Show loading state when null:

+    val serverConfigState = viewModel.state.value
+    if (serverConfigState == null) {
+        // Show loading or return early
+        return
+    }
+
     Box(modifier = Modifier.fillMaxSize()) {
         UpdateServerConfigScreenContent(
             modifier = modifier,
-            serverConfig = viewModel.state.value!!,
+            serverConfig = serverConfigState,
♻️ Duplicate comments (2)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt (2)

286-301: Replace hardcoded Color.LightGray with theme color.

The divider uses hardcoded Color.LightGray which won't adapt to dark/light theme changes. Based on past review comments about hardcoded colors, use a theme-based color.

🔎 Proposed fix
                     HorizontalDivider(
                         modifier = Modifier.weight(1f),
-                        color = Color.LightGray,
+                        color = MaterialTheme.colorScheme.outlineVariant,
                     )
                     // ... Text ...
                     HorizontalDivider(
                         modifier = Modifier.weight(1f),
-                        color = Color.LightGray,
+                        color = MaterialTheme.colorScheme.outlineVariant,
                     )

595-600: Replace hardcoded Color.Gray with theme color.

Using Color.Gray won't adapt to theme changes. Use a theme-based color for better dark/light mode support.

🔎 Proposed fix
             Text(
                 text = stringResource(Res.string.feature_settings_restart_application),
                 style = MaterialTheme.typography.bodyMedium,
-                color = Color.Gray,
+                color = MaterialTheme.colorScheme.onSurfaceVariant,
                 textAlign = TextAlign.Center,
             )
🧹 Nitpick comments (1)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt (1)

526-532: Use padding instead of hardcoded spaces in text.

The leading " " spaces are a fragile way to add spacing. Use Modifier.padding on the Text or adjust button content padding instead.

🔎 Proposed fix
                     Text(
-                        "  " +
-                            stringResource(
-                                Res.string.feature_settings_update_config_btn_text,
-                            ).uppercase(),
+                        stringResource(Res.string.feature_settings_update_config_btn_text).uppercase(),
+                        modifier = Modifier.padding(start = DesignToken.padding.small),
                         fontFamily = FontFamily.SansSerif,
                     )
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a30dabf and c448375.

📒 Files selected for processing (1)
  • feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt
🧰 Additional context used
🧬 Code graph analysis (1)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt (1)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigViewModel.kt (1)
  • onEvent (79-141)
⏰ 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: PR Checks / Static Analysis Check
🔇 Additional comments (2)
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt (2)

181-188: Good migration to DesignToken and MaterialTheme.

The styling changes properly use DesignToken for padding, spacing, and shapes, and MaterialTheme.colorScheme for colors. This is consistent with the codebase's design system approach.


558-634: Clean dialog implementation with proper countdown UX.

The RestartCountdownDialog is well-structured with:

  • Clear visual hierarchy (success icon, title, subtitle, progress, action)
  • Proper use of DesignToken for sizing and spacing
  • Correct countdown logic with auto-dismiss

The circular progress indicator effectively communicates the remaining time before restart.

Comment on lines +540 to +547
private fun RestartCountdownDialog(
durationSeconds: Int = 5,
dismissText: String? = null,
onDismiss: () -> Unit,
modifier: Modifier = Modifier,
onAboutToEnd: () -> Unit = {},
) {
var countdown by rememberSaveable { mutableStateOf(durationSeconds) }

val progress = countdown.toFloat() / durationSeconds.toFloat()
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

Guard against division by zero.

If durationSeconds is passed as 0, line 547 will cause a division by zero. While the default is 5, the function is private and could be called with 0.

🔎 Proposed fix
 private fun RestartCountdownDialog(
     durationSeconds: Int = 5,
     onDismiss: () -> Unit,
     modifier: Modifier = Modifier,
 ) {
+    require(durationSeconds > 0) { "durationSeconds must be positive" }
     var countdown by rememberSaveable { mutableStateOf(durationSeconds) }
 
-    val progress = countdown.toFloat() / durationSeconds.toFloat()
+    val progress = countdown.toFloat() / durationSeconds.coerceAtLeast(1).toFloat()
📝 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
private fun RestartCountdownDialog(
durationSeconds: Int = 5,
dismissText: String? = null,
onDismiss: () -> Unit,
modifier: Modifier = Modifier,
onAboutToEnd: () -> Unit = {},
) {
var countdown by rememberSaveable { mutableStateOf(durationSeconds) }
val progress = countdown.toFloat() / durationSeconds.toFloat()
private fun RestartCountdownDialog(
durationSeconds: Int = 5,
onDismiss: () -> Unit,
modifier: Modifier = Modifier,
) {
require(durationSeconds > 0) { "durationSeconds must be positive" }
var countdown by rememberSaveable { mutableStateOf(durationSeconds) }
val progress = countdown.toFloat() / durationSeconds.coerceAtLeast(1).toFloat()
🤖 Prompt for AI Agents
In
feature/settings/src/commonMain/kotlin/com/mifos/feature/settings/updateServer/UpdateServerConfigScreen.kt
around lines 540 to 547, the progress calculation can divide by zero if
durationSeconds is 0; change the logic to guard against that by normalizing the
denominator before division (e.g., use a safeDuration = max(1, durationSeconds)
or check if durationSeconds <= 0 and set progress to 0f), and then compute
progress using that safe value; ensure any other uses of durationSeconds in this
function respect the same guard so no other divisions or assumptions about >0
occur.

@therajanmaurya therajanmaurya enabled auto-merge (squash) January 2, 2026 15:25
@therajanmaurya therajanmaurya merged commit 1f9a486 into openMF:development Jan 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants