Skip to content

Conversation

@capcom6
Copy link
Owner

@capcom6 capcom6 commented Nov 1, 2025

Summary by CodeRabbit

  • Improvements
    • Settings import routines now report whether any values changed, enabling callers to know if updates occurred.
    • Individual modules detect per-setting changes and update storage only when values differ, avoiding unnecessary writes.
    • Notifications and downstream actions are triggered only when real changes occur, reducing redundant updates, processing, and potential side effects.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 1, 2025

🤖 Pull request artifacts

file commit
app-release.apk d456d3f
app-release.aab d456d3f
app-insecure.apk d456d3f
app-insecure.aab d456d3f

@capcom6
Copy link
Owner Author

capcom6 commented Nov 1, 2025

@coderabbitai full review

@coderabbitai
Copy link

coderabbitai bot commented Nov 1, 2025

✅ Actions performed

Full review triggered.

@coderabbitai
Copy link

coderabbitai bot commented Nov 1, 2025

Walkthrough

Importer.import now returns a Boolean; each module's import was updated to return true when any handled key actually changed. SettingsService collects those Booleans and only emits notifications when at least one module reported a change.

Changes

Cohort / File(s) Summary
Interface definition
app/src/main/java/me/capcom/smsgateway/modules/settings/Importer.kt
Changed signature from fun import(data: Map<String, *>) to fun import(data: Map<String, *>): Boolean.
Service handler
app/src/main/java/me/capcom/smsgateway/modules/settings/SettingsService.kt
Calls module imports with map to collect Boolean results; early-returns when none changed and only emits notifications if at least one result is true.
Settings implementations — generic pattern
app/src/main/java/me/capcom/smsgateway/modules/*/...Settings.kt
Each import now maps input entries to per-key changed booleans (parsing/validation where applicable), compares parsed/new values to current state before writing, updates storage accordingly, returns overall .any { it }, and returns false for unrecognized keys.
Encryption
app/src/main/java/me/capcom/smsgateway/modules/encryption/EncryptionSettings.kt
import now returns Boolean; PASSPHRASE computes newValue, sets changed = passphrase != newValue, updates storage and returns changed.
Gateway
app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewaySettings.kt
import now returns Boolean; handles CLOUD_URL (defaulting to PUBLIC_URL, validates HTTPS, compares and stores serverUrl) and PRIVATE_TOKEN (compares/stores), returns per-entry changed flags aggregated with .any { it }.
Logs
app/src/main/java/me/capcom/smsgateway/modules/logs/LogsSettings.kt
import now returns Boolean; handles LIFETIME_DAYS with parsing/validation, compares to current lifetimeDays, updates storage and returns change indicator.
Messages
app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt
import now returns Boolean; handles many keys (SEND_INTERVAL_MIN/MAX, LIMIT_PERIOD, LIMIT_VALUE, SIM_SELECTION_MODE, PROCESSING_ORDER, LOG_LIFETIME_DAYS) with parsing/validation, compares and stores values, returns overall changed status.
Ping
app/src/main/java/me/capcom/smsgateway/modules/ping/PingSettings.kt
import now returns Boolean; handles INTERVAL_SECONDS, parses value, compares to intervalSeconds, updates storage and returns change indicator.
Webhooks
app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt
import now returns Boolean; handles INTERNET_REQUIRED, RETRY_COUNT, SIGNING_KEY with parsing/validation, compares and stores values, returns overall changed status.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant SettingsService
    participant ModuleA
    participant ModuleB

    Client->>SettingsService: update(importedData)

    rect rgb(230,245,255)
    Note over SettingsService: call each Module.import(data) and collect Boolean results
    SettingsService->>ModuleA: import(data)
    ModuleA-->>SettingsService: true / false
    SettingsService->>ModuleB: import(data)
    ModuleB-->>SettingsService: true / false
    end

    rect rgb(235,255,230)
    Note over SettingsService: aggregate results (.any { it })
    alt any true
        SettingsService->>SettingsService: emit change notification
    else all false
        SettingsService-->>Client: return early (no notification)
    end
    end

    SettingsService-->>Client: Done
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to per-module parsing/validation (numeric parsing, defaults, bounds).
  • Verify comparisons use the correct current-state fields and types.
  • Confirm SettingsService notification gating correctly handles mixed true/false returns.

Possibly related PRs

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 '[settings] notify user on real changes only' accurately describes the main objective of the pull request, which is to modify the import/notify behavior to only notify users when actual changes occur.
✨ 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 settings/fix-changes-notification

📜 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 df69365 and d456d3f.

📒 Files selected for processing (8)
  • app/src/main/java/me/capcom/smsgateway/modules/encryption/EncryptionSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewaySettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/logs/LogsSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/ping/PingSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/settings/Importer.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/settings/SettingsService.kt (2 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • app/src/main/java/me/capcom/smsgateway/modules/encryption/EncryptionSettings.kt
  • app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewaySettings.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt
  • app/src/main/java/me/capcom/smsgateway/modules/settings/SettingsService.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build insecure / build-apk
  • GitHub Check: Build release / build-apk

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: 4

🧹 Nitpick comments (4)
app/src/main/java/me/capcom/smsgateway/modules/settings/SettingsService.kt (1)

51-53: Simplify the change detection condition.

The condition !changed.any { it == true } works correctly but can be simplified.

Apply this diff:

-        if (!changed.any { it == true }) {
+        if (changed.none { it == true }) {
             return
         }

Or, if you adopt mapNotNull from the previous suggestion:

-        if (!changed.any { it == true }) {
+        if (changed.none { it }) {
             return
         }
app/src/main/java/me/capcom/smsgateway/modules/encryption/EncryptionSettings.kt (1)

43-55: Improve type safety in the comparison.

Line 47 compares passphrase (String?) with it.value (Any?) without explicit type conversion. While this may work due to Kotlin's equality semantics, it's clearer and safer to explicitly convert the value to String.

Apply this diff:

             when (it.key) {
                 PASSPHRASE -> {
-                    val changed = passphrase != it.value
-                    storage.set(it.key, it.value?.toString())
+                    val newValue = it.value?.toString()
+                    val changed = passphrase != newValue
+                    storage.set(it.key, newValue)
                     changed
                 }

This makes the type conversion explicit and avoids potential confusion.

app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewaySettings.kt (1)

69-75: Improve type safety in the comparison.

Line 70 compares privateToken (String?) with it.value (Any?) without explicit type conversion, similar to the issue in EncryptionSettings.

Apply this diff:

                 PRIVATE_TOKEN -> {
-                    val changed = privateToken != it.value
+                    val newValue = it.value?.toString()
+                    val changed = privateToken != newValue

-                    storage.set(it.key, it.value?.toString())
+                    storage.set(it.key, newValue)

                     changed
                 }
app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt (1)

63-69: Minor type safety improvement.

Line 64 compares this.signingKey (String) with value?.toString() (String?) directly. While this works, extracting the new value makes the comparison more explicit.

Apply this diff:

                 SIGNING_KEY -> {
-                    val changed = this.signingKey != value?.toString()
+                    val newValue = value?.toString()
+                    val changed = newValue != null && this.signingKey != newValue

-                    storage.set(key, value?.toString())
+                    if (newValue != null) {
+                        storage.set(key, newValue)
+                    }

                     changed
                 }

Note: This also adds a null check to avoid storing null signing keys, maintaining the invariant that signingKey always has a value.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4aa519d and b7a7032.

📒 Files selected for processing (8)
  • app/src/main/java/me/capcom/smsgateway/modules/encryption/EncryptionSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewaySettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/logs/LogsSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/ping/PingSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/settings/Importer.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/settings/SettingsService.kt (2 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt (1 hunks)
🔇 Additional comments (6)
app/src/main/java/me/capcom/smsgateway/modules/settings/SettingsService.kt (1)

41-49: Verify nullable handling in change detection.

The map operation produces List<Boolean?> because (it as? Importer)?.import(...) returns null when the cast fails or the interface is not implemented. The subsequent check on line 51 treats null as "no change," which is correct but implicit.

Consider making the null handling explicit for clarity:

-        val changed = data.map { (key, value) ->
+        val changed = data.mapNotNull { (key, value) ->
             try {
                 settings[key]?.let {
                     (it as? Importer)?.import(value as Map<String, *>)
                 }
             } catch (e: IllegalArgumentException) {
                 throw IllegalArgumentException("Failed to import $key: ${e.message}", e)
             }
         }

Using mapNotNull makes it clear that null results (from settings that don't implement Importer) are filtered out before checking for changes.

app/src/main/java/me/capcom/smsgateway/modules/settings/Importer.kt (1)

4-4: LGTM!

The interface change to return Boolean is straightforward and enables change detection across all implementations.

app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewaySettings.kt (1)

56-67: LGTM!

The URL validation and change detection for CLOUD_URL are correctly implemented.

app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (1)

138-144: LGTM!

The change detection logic for LIMIT_PERIOD, LIMIT_VALUE, SIM_SELECTION_MODE, PROCESSING_ORDER, and LOG_LIFETIME_DAYS is correctly implemented with proper type conversions and validation.

Also applies to: 146-157, 159-168, 170-179, 181-191

app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt (2)

42-48: LGTM!

The change detection for INTERNET_REQUIRED correctly converts and compares boolean values.


50-61: LGTM!

The change detection for RETRY_COUNT correctly validates the value, handles the comparison, and updates storage.

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

♻️ Duplicate comments (3)
app/src/main/java/me/capcom/smsgateway/modules/ping/PingSettings.kt (1)

31-41: Unnecessary float conversion for integer values.

Line 32 uses value?.toString()?.toFloat()?.toInt() which unnecessarily converts through Float and can introduce precision issues for large integers. This issue was previously flagged in past reviews.

app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (2)

116-126: Unnecessary float conversion for integer values.

Line 117 uses the unnecessary float conversion pattern value?.toString()?.toFloat()?.toInt() for SEND_INTERVAL_MIN. This was previously flagged in past reviews.


128-138: Unnecessary float conversion for integer values.

Line 129 uses the unnecessary float conversion pattern value?.toString()?.toFloat()?.toInt() for SEND_INTERVAL_MAX. This was previously flagged in past reviews.

🧹 Nitpick comments (4)
app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (3)

140-146: Eliminate duplicate valueOf call.

Period.valueOf(it.toString()) is evaluated twice (lines 141 and 143). Compute it once and reuse to improve readability and avoid redundant work.

Apply this diff:

                 LIMIT_PERIOD -> {
-                    val changed = this.limitPeriod != value?.let { Period.valueOf(it.toString()) }
-
-                    storage.set(key, value?.let { Period.valueOf(it.toString()) })
+                    val newValue = value?.let { Period.valueOf(it.toString()) }
+                    val changed = this.limitPeriod != newValue
+
+                    storage.set(key, newValue)

                     changed
                 }

161-170: Eliminate duplicate valueOf call.

SimSelectionMode.valueOf(it.toString()) is evaluated twice (lines 162-163 and 165-167). Compute it once and reuse.

Apply this diff:

                 SIM_SELECTION_MODE -> {
-                    val changed =
-                        this.simSelectionMode != value?.let { SimSelectionMode.valueOf(it.toString()) }
-
-                    storage.set(
-                        key,
-                        value?.let { SimSelectionMode.valueOf(it.toString()) })
+                    val newValue = value?.let { SimSelectionMode.valueOf(it.toString()) }
+                    val changed = this.simSelectionMode != newValue
+
+                    storage.set(key, newValue)

                     changed
                 }

172-181: Eliminate duplicate valueOf call.

ProcessingOrder.valueOf(it.toString()) is evaluated twice (lines 173-174 and 176-178). Compute it once and reuse.

Apply this diff:

                 PROCESSING_ORDER -> {
-                    val changed =
-                        this.processingOrder != value?.let { ProcessingOrder.valueOf(it.toString()) }
-
-                    storage.set(
-                        key,
-                        value?.let { ProcessingOrder.valueOf(it.toString()) })
+                    val newValue = value?.let { ProcessingOrder.valueOf(it.toString()) }
+                    val changed = this.processingOrder != newValue
+
+                    storage.set(key, newValue)

                     changed
                 }
app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt (1)

42-48: Eliminate duplicate toBoolean call.

value?.toString()?.toBoolean() is evaluated twice (lines 43 and 45). Compute it once and reuse for consistency with the SIGNING_KEY case (lines 63-70).

Apply this diff:

                 INTERNET_REQUIRED -> {
-                    val changed = this.internetRequired != value?.toString()?.toBoolean()
-
-                    storage.set(key, value?.toString()?.toBoolean())
+                    val newValue = value?.toString()?.toBoolean()
+                    val changed = this.internetRequired != newValue
+
+                    storage.set(key, newValue)

                     changed
                 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b7a7032 and 7d869c5.

📒 Files selected for processing (7)
  • app/src/main/java/me/capcom/smsgateway/modules/encryption/EncryptionSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewaySettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/logs/LogsSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/ping/PingSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/settings/SettingsService.kt (2 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • app/src/main/java/me/capcom/smsgateway/modules/logs/LogsSettings.kt
  • app/src/main/java/me/capcom/smsgateway/modules/settings/SettingsService.kt
  • app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewaySettings.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build insecure / build-apk
  • GitHub Check: Build release / build-apk
🔇 Additional comments (3)
app/src/main/java/me/capcom/smsgateway/modules/encryption/EncryptionSettings.kt (1)

43-56: Clean implementation of change detection.

The implementation correctly computes the new value once, compares it with the current value, stores it, and returns the change flag. This is the correct pattern.

app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt (2)

50-61: Good implementation pattern.

The RETRY_COUNT case correctly computes retryCount once, validates it, compares it, and stores it. This is the recommended pattern.


63-70: Good implementation pattern.

The SIGNING_KEY case correctly computes newValue once, compares it, and stores it. This is the recommended pattern that should be followed by the other cases.

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: 4

♻️ Duplicate comments (2)
app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (2)

128-138: Fix the float conversion for integer values.

The toString()?.toFloat()?.toInt() pattern is unnecessary and lossy. Use toIntOrNull() for direct integer parsing.

Apply this diff:

                SEND_INTERVAL_MAX -> {
-                    val newValue = value?.toString()?.toFloat()?.toInt()
+                    val newValue = value?.toString()?.toIntOrNull()
                    val changed = this.sendIntervalMax != newValue

                    storage.set(
                        key,
                        newValue?.toString()
                    )

                    changed
                }

Note: This issue was also flagged in previous review comments.


116-126: Fix float conversion and false positive change detection.

Two issues:

  1. Float conversion (previously flagged): The toString()?.toFloat()?.toInt() pattern is unnecessary and lossy for integer values.

  2. False positive detection: When storage is null and importing null, this reports a change because this.sendIntervalMin (returns 0 via default) is compared with null, evaluating to 0 != nulltrue. However, the storage remains null → null (no actual change).

Apply this diff to fix both issues:

                SEND_INTERVAL_MIN -> {
-                    val newValue = value?.toString()?.toFloat()?.toInt()
+                    val newValue = value?.toString()?.toIntOrNull() ?: 0
                    val changed = this.sendIntervalMin != newValue

                    storage.set(
                        key,
-                        newValue?.toString()
+                        newValue.toString()
                    )

                    changed
                }

This applies the same default (0) to imported null values as the getter does, ensuring consistent effective-value comparison.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d869c5 and 7d7cdc9.

📒 Files selected for processing (2)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build release / build-apk
  • GitHub Check: Build insecure / build-apk
🔇 Additional comments (3)
app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (3)

110-110: Method signature change looks good.

The addition of Boolean return type correctly implements the PR objective to detect and report actual changes.


180-190: LGTM!

The change detection logic is correct. The nullable property with validation is properly handled, and the comparison accurately detects effective value changes.


192-194: LGTM!

The aggregation logic correctly returns true only when at least one key reports a change. The else -> false for unrecognized keys is appropriate.

@capcom6 capcom6 force-pushed the settings/fix-changes-notification branch from a43bfea to a233f85 Compare November 2, 2025 23:41
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

♻️ Duplicate comments (4)
app/src/main/java/me/capcom/smsgateway/modules/ping/PingSettings.kt (1)

32-38: Avoid float round-trips when parsing integers.

Line 32 currently funnels integer parsing through toFloat()?.toInt(). That round-trip can silently round large values (e.g., 16,777,217 becomes 16,777,216) and breaks the PR goal of only flagging real changes. Parse the integer directly instead.

-                    val newValue = value?.toString()?.toFloat()?.toInt()
+                    val newValue = value?.toString()?.toIntOrNull()
app/src/main/java/me/capcom/smsgateway/modules/logs/LogsSettings.kt (1)

51-55: Parse integers without float conversion.

Line 51 repeats the toFloat()?.toInt() round-trip, introducing the same precision-loss risk noted previously. Switch to direct integer parsing so unchanged large values aren’t misdetected as changes.

-                    val newValue = it.value?.toString()?.toFloat()?.toInt()
+                    val newValue = it.value?.toString()?.toIntOrNull()
app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (2)

116-126: Fix unnecessary float conversion and false positive for null values.

Line 117 uses the lossy pattern ?.toString()?.toFloat()?.toInt() for an integer setting, and Line 118 compares the getter (which defaults to 0) with a nullable newValue. When both storage and import are null, this reports 0 != null as a change even though the effective value remains 0.

Apply this diff to parse directly to Int and apply the default before comparison:

                SEND_INTERVAL_MIN -> {
-                    val newValue = value?.toString()?.toFloat()?.toInt()
+                    val newValue = value?.toString()?.toIntOrNull() ?: 0
                    val changed = this.sendIntervalMin != newValue

                    storage.set(
                        key,
-                        newValue?.toString()
+                        newValue.toString()
                    )

                    changed
                }

128-138: Remove unnecessary float conversion.

Line 129 uses the lossy pattern ?.toString()?.toFloat()?.toInt() for an integer setting. Parse directly to Int.

Apply this diff:

                SEND_INTERVAL_MAX -> {
-                    val newValue = value?.toString()?.toFloat()?.toInt()
+                    val newValue = value?.toString()?.toIntOrNull()
                    val changed = this.sendIntervalMax != newValue

                    storage.set(
                        key,
                        newValue?.toString()
                    )

                    changed
                }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a43bfea and a233f85.

📒 Files selected for processing (8)
  • app/src/main/java/me/capcom/smsgateway/modules/encryption/EncryptionSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewaySettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/logs/LogsSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/ping/PingSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/settings/Importer.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/settings/SettingsService.kt (2 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/java/me/capcom/smsgateway/modules/settings/SettingsService.kt
🔇 Additional comments (7)
app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (7)

110-111: LGTM! Change tracking approach is sound.

The function signature now returns Boolean, and the map { ... }.any { it } pattern correctly aggregates per-entry change flags to report whether any setting changed.


140-147: Good fix! Default is now applied before comparison.

Line 141 correctly applies ?: Period.Disabled to match the getter's default (Line 50), eliminating the false positive when importing null with null storage.


149-160: Good fix! Default is now applied in comparison.

Line 155 correctly uses (limitValue ?: 0) to match the getter's default (Line 52), eliminating the false positive when importing null with null storage.


162-170: Good fix! Default is now applied before comparison.

Lines 163-164 correctly apply ?: SimSelectionMode.OSDefault to match the getter's default (Line 55), eliminating the false positive when importing null with null storage.


172-180: Good fix! Default is now applied before comparison.

Lines 173-174 correctly apply ?: ProcessingOrder.LIFO to match the getter's default (Line 61), eliminating the false positive when importing null with null storage.


194-194: LGTM! Unhandled keys correctly return false.

The else branch ensures that unrecognized keys don't contribute to the change flag.


196-196: LGTM! Aggregation correctly tracks if any entry changed.

The .any { it } aggregation returns true if any setting entry reported a change.

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: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a233f85 and d44318a.

📒 Files selected for processing (2)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build insecure / build-apk
  • GitHub Check: Build release / build-apk

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

♻️ Duplicate comments (3)
app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (3)

182-192: False positive due to getter's filter and unnecessary float conversion.

Line 188 compares the getter's filtered value (which returns null for values ≤ 0 via takeIf { it > 0 } at line 58) against the raw imported value. This causes false positives when importing non-positive values if such values exist in storage.

Example: If storage contains -5, the getter returns null. Importing -5 again would hit the validation error. But importing null compares null != null which works correctly only by coincidence.

Additionally, line 183 uses an unnecessary float conversion for an integer value.

Apply this diff to fix both issues:

                LOG_LIFETIME_DAYS -> {
-                    val logLifetimeDays = value?.toString()?.toFloat()?.toInt()
+                    val logLifetimeDays = value?.toString()?.toIntOrNull()
                    if (logLifetimeDays != null && logLifetimeDays < 1) {
                        throw IllegalArgumentException("Log lifetime days must be >= 1")
                    }

-                    val changed = this.logLifetimeDays != logLifetimeDays
+                    val effectiveNew = logLifetimeDays?.takeIf { it > 0 }
+                    val changed = this.logLifetimeDays != effectiveNew
                    storage.set(key, logLifetimeDays?.toString())

                    changed
                }

This applies the same filter as the getter before comparison and removes the float conversion.


128-138: Remove unnecessary float conversion for integer value.

Line 129 unnecessarily converts through float for an integer setting.

Apply this diff:

                SEND_INTERVAL_MAX -> {
-                    val newValue = value?.toString()?.toFloat()?.toInt()
+                    val newValue = value?.toString()?.toIntOrNull()
                    val changed = this.sendIntervalMax != newValue

                    storage.set(
                        key,
                        newValue?.toString()
                    )

                    changed
                }

116-126: False positive when importing null for SEND_INTERVAL_MIN.

Line 118 compares the getter's default value (0) against a nullable newValue. When storage is empty and you import null, this reports a change (0 != null = true) even though the effective value remains 0 before and after import.

Additionally, line 117 uses an unnecessary float conversion for an integer value.

Apply this diff to fix both issues:

                SEND_INTERVAL_MIN -> {
-                    val newValue = value?.toString()?.toFloat()?.toInt()
-                    val changed = this.sendIntervalMin != newValue
+                    val newValue = value?.toString()?.toIntOrNull() ?: 0
+                    val changed = this.sendIntervalMin != newValue

                    storage.set(
                        key,
-                        newValue?.toString()
+                        newValue.toString()
                    )

                    changed
                }

This ensures null imports are treated as 0 (consistent with the getter's default) and removes the unnecessary float conversion.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d44318a and d8523f4.

📒 Files selected for processing (2)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build release / build-apk
  • GitHub Check: Build insecure / build-apk
🔇 Additional comments (4)
app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (4)

140-147: LGTM! Default handling fixed.

The default Period.Disabled is now correctly applied to newValue before comparison (line 141), eliminating the false positive flagged in previous reviews.


162-170: LGTM! Default handling fixed.

The default SimSelectionMode.OSDefault is correctly applied to newValue before comparison (lines 163-164), eliminating the false positive flagged in previous reviews.


172-180: LGTM! Default handling fixed.

The default ProcessingOrder.LIFO is correctly applied to newValue before comparison (lines 173-174), eliminating the false positive flagged in previous reviews.


194-196: LGTM! Aggregation logic is correct.

The else branch correctly returns false for unknown keys, and the .any { it } aggregation (line 196) properly returns true only when at least one setting has actually changed.

@capcom6 capcom6 force-pushed the settings/fix-changes-notification branch from d8523f4 to 69fc3f1 Compare November 10, 2025 23:36
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: 5

♻️ Duplicate comments (2)
app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (2)

150-158: Please drop the float round-trip for limit_value.
Line 151 still parses with toFloat()?.toInt(), so limit_value = 16777217 would be stored as 16777216. This was already flagged earlier; we should parse without losing precision.

-                    val limitValue = value?.toString()?.toFloat()?.toInt()
+                    val limitValue = value?.toString()?.toDoubleOrNull()?.toInt()

117-126: Stop flagging null → default transitions on send_interval_min.
Line 118 compares the raw newValue to sendIntervalMin, which falls back to 0 whenever nothing is stored. If the import sends null (or the backup omitted the key) and we were already at the default, sendIntervalMin is 0 while newValue is null, so changed becomes true even though we persist null and remain at the default. Normalise the incoming value to the same effective representation and avoid the float round-trip.

-                    val newValue = value?.toString()?.toFloat()?.toInt()
-                    val changed = this.sendIntervalMin != newValue
-
-                    storage.set(
-                        key,
-                        newValue?.toString()
-                    )
+                    val rawValue = value?.toString()?.toDoubleOrNull()?.toInt()
+                    val normalisedNew = rawValue ?: 0
+                    val changed = sendIntervalMin != normalisedNew
+
+                    storage.set(key, rawValue?.toString())
🧹 Nitpick comments (1)
app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewaySettings.kt (1)

56-67: Consider validating empty strings for CLOUD_URL.

The current validation (lines 58-60) only checks non-null URLs for the https:// prefix. Empty strings would pass through but are unlikely to be valid URLs. Consider whether empty strings should be rejected or treated as null.

Example enhancement:

                CLOUD_URL -> {
-                   val url = it.value?.toString()
+                   val url = it.value?.toString()?.takeIf { it.isNotEmpty() }
                    if (url != null && !url.startsWith("https://")) {
                        throw IllegalArgumentException("url must start with https://")
                    }

                    val changed = storage.get<String?>(CLOUD_URL) != url

                    storage.set(it.key, url)

                    changed
                }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d8523f4 and 69fc3f1.

📒 Files selected for processing (8)
  • app/src/main/java/me/capcom/smsgateway/modules/encryption/EncryptionSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewaySettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/logs/LogsSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/ping/PingSettings.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/settings/Importer.kt (1 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/settings/SettingsService.kt (2 hunks)
  • app/src/main/java/me/capcom/smsgateway/modules/webhooks/WebhooksSettings.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/src/main/java/me/capcom/smsgateway/modules/settings/Importer.kt
  • app/src/main/java/me/capcom/smsgateway/modules/settings/SettingsService.kt
🔇 Additional comments (2)
app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewaySettings.kt (2)

69-76: LGTM: PRIVATE_TOKEN change detection is correct.

The comparison correctly checks the actual stored value (which can be null) against the new value.


53-55: LGTM: Overall approach aligns with PR objective.

The refactored implementation using map + any correctly aggregates per-entry change flags and returns true only when at least one setting actually changed, which fulfills the PR objective to "notify user on real changes only."

Also applies to: 78-80

@capcom6 capcom6 force-pushed the settings/fix-changes-notification branch from df69365 to d456d3f Compare November 11, 2025 02:02
@capcom6 capcom6 merged commit 3349896 into master Nov 11, 2025
3 checks passed
@capcom6 capcom6 deleted the settings/fix-changes-notification branch November 11, 2025 12:48
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.

2 participants