Skip to content

feat: refine push notification handling and lifecycle support#14

Merged
pitzcarraldo merged 4 commits intomainfrom
feat/push-lifecycle
Dec 17, 2025
Merged

feat: refine push notification handling and lifecycle support#14
pitzcarraldo merged 4 commits intomainfrom
feat/push-lifecycle

Conversation

@pitzcarraldo
Copy link
Contributor

@pitzcarraldo pitzcarraldo commented Dec 16, 2025

  • Updated onMessage to trigger only in the foreground and introduced onBackgroundMessage for handling background notifications.
  • Standardized naming conventions and storage keys for improved clarity and internal consistency.
  • Updated dependencies and added lifecycle management support for detecting when the app is in the foreground.

Summary by CodeRabbit

  • Changed

    • Push notifications: onMessage now fires only in foreground; onBackgroundMessage only in background/terminated.
    • Internal storage/key and initialization naming updated for consistency (no public API changes).
  • New Features

    • Sample app: added runtime configuration loading (initialize) and exposed config property for simpler setup.
  • Chores

    • Bumped release to 1.3.2; updated README and changelog.
    • Added lifecycle/process dependency and sample app assets/docs.

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

- Ensure `onMessage` is called only in the foreground and introduce `onBackgroundMessage` for background scenarios.
- Standardize internal variable naming and storage keys for clarity.
- Update dependencies and add lifecycle support for foreground detection.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 16, 2025

Walkthrough

Introduces release 1.3.2: updates changelog and README, adds androidx.lifecycle.process dependency, changes push notification routing so foreground uses onMessage and background/terminated uses onBackgroundMessage, renames several internal variables and storage keys, and adds sample app configuration loading; no public API signature removals detected.

Changes

Cohort / File(s) Summary
Release/version & docs
CHANGELOG.md, README.md, gradle/libs.versions.toml
Bumped clix to 1.3.2, added changelog entry, updated README version, and added androidx-lifecycle version + androidx-lifecycle-process library entry.
Build dependency
clix/build.gradle.kts, samples/basic-app/build.gradle.kts
Added implementation(libs.androidx.lifecycle.process) and Kotlin Serialization plugin + kotlinx.serialization.json dependency in sample.
Push notification handling
clix/src/main/kotlin/so/clix/core/ClixNotification.kt
Detects app foreground via ProcessLifecycleOwner; routes notifications to onMessage in foreground (with suppression when handler returns false/throws) and to onBackgroundMessage when background/terminated, with adjusted logging and try/catch behavior.
Core SDK internal refactor
clix/src/main/kotlin/so/clix/core/Clix.kt
Renamed internal identifiers (e.g., COROUTINE_CONTEXTcoroutineContext), replaced initializeLock with InitializeLock, and changed config storage key (CONFIG_STORAGE_KEYCONFIG_KEY) across init/sync/persistence code.
Token storage key changes & tests
clix/src/main/kotlin/so/clix/services/TokenService.kt, clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt
Renamed internal storage keys (clix_current_tokenclix_current_push_token, clix_previous_tokensclix_push_tokens) and updated tests accordingly; token logic unchanged.
Sample app configuration & assets
samples/basic-app/src/main/kotlin/.../ClixConfiguration.kt, samples/basic-app/src/main/kotlin/.../BasicApplication.kt, samples/basic-app/src/main/kotlin/.../ContentView.kt, samples/basic-app/src/main/assets/ClixConfig.json.example, samples/basic-app/README.md
Added config JSON example and sample README; replaced public constant config usage with ClixConfiguration.initialize(context) and a public config property (lateinit with private setter); updated sample usages to ClixConfiguration.config.*.
Miscellaneous
.gitignore
Added ignore rule for ClixConfig*.json alongside existing google-services.json rule.

Possibly related PRs

Suggested reviewers

  • nyanxyz

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% 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: refining push notification handling with new foreground/background logic and adding lifecycle support for app state detection.
✨ 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 feat/push-lifecycle

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

Copy link
Contributor

@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)
clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt (1)

53-53: Tests correctly updated to use new storage keys.

The test updates align with the renamed storage keys in TokenService.kt. However, these tests directly reference internal storage key strings, creating tight coupling to implementation details. Consider extracting the key constants or testing through the TokenService public API where possible to reduce maintenance burden.

gradle/libs.versions.toml (1)

22-23: Consider using Firebase BOM for version management.

Per coding guidelines, Firebase should be managed via BOM and version catalog. Currently firebase-messaging uses a direct version reference. Consider using the Firebase BOM for consistent Firebase dependency management across the project.

+firebase-bom = "33.7.0"
 firebase-messaging = "24.0.0"

And update the library entry to use BOM:

-firebase-messaging-ktx = { group = "com.google.firebase", name = "firebase-messaging-ktx", version.ref = "firebase-messaging" }
+firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebase-bom" }
+firebase-messaging-ktx = { group = "com.google.firebase", name = "firebase-messaging-ktx" }

Based on coding guidelines: "Use Firebase via BOM and version catalog".

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 90704ce and 2315514.

📒 Files selected for processing (8)
  • CHANGELOG.md (1 hunks)
  • README.md (1 hunks)
  • clix/build.gradle.kts (1 hunks)
  • clix/src/main/kotlin/so/clix/core/Clix.kt (5 hunks)
  • clix/src/main/kotlin/so/clix/core/ClixNotification.kt (3 hunks)
  • clix/src/main/kotlin/so/clix/services/TokenService.kt (1 hunks)
  • clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt (7 hunks)
  • gradle/libs.versions.toml (3 hunks)
🧰 Additional context used
📓 Path-based instructions (14)
clix/src/test/kotlin/so/clix/**

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Mirror main source structure for unit tests under clix/src/test/kotlin/so/clix

Files:

  • clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt
clix/src/{test,androidTest}/kotlin/**/*.kt

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

clix/src/{test,androidTest}/kotlin/**/*.kt: Use JUnit4/Kotest for unit tests and AndroidX Test/Robolectric for instrumentation
Name tests using Given-When-Then or 'it(target) should ...' style
Use property-based tests for pure functions where applicable
Use Stub and Spy patterns via MockK for doubles
Prefer Stub/MockK doubles for tests

Files:

  • clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt
clix/src/main/kotlin/so/clix/**

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Follow the specified library source structure under clix/src/main/kotlin/so/clix/(core|models|notification|services|utils)

Files:

  • clix/src/main/kotlin/so/clix/services/TokenService.kt
  • clix/src/main/kotlin/so/clix/core/Clix.kt
  • clix/src/main/kotlin/so/clix/core/ClixNotification.kt
clix/src/main/kotlin/so/clix/services/**/*.kt

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

clix/src/main/kotlin/so/clix/services/**/*.kt: Classes interacting with external services must use Service or Repository suffix
Handle side effects explicitly within repository/service classes

Files:

  • clix/src/main/kotlin/so/clix/services/TokenService.kt
clix/src/main/kotlin/so/clix/{core,services}/**/*.kt

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Throw exceptions only for unrecoverable errors

Files:

  • clix/src/main/kotlin/so/clix/services/TokenService.kt
  • clix/src/main/kotlin/so/clix/core/Clix.kt
  • clix/src/main/kotlin/so/clix/core/ClixNotification.kt
clix/src/main/kotlin/**/*.kt

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

clix/src/main/kotlin/**/*.kt: Use Kotlin Coroutines for asynchronous operations
Ensure thread safety for shared mutable state
Write small, pure, composable functions; favor immutability and explicit side effects
Use descriptive names and prefer expression-style functions where clear
Order declarations Public → Internal → Private
Avoid reflection, annotations, and metaprogramming unless necessary
Do not use service locators or singletons (unless absolutely necessary)
No reflection under any circumstances
Use DataStore Preferences for local storage

Files:

  • clix/src/main/kotlin/so/clix/services/TokenService.kt
  • clix/src/main/kotlin/so/clix/core/Clix.kt
  • clix/src/main/kotlin/so/clix/core/ClixNotification.kt
clix/src/main/kotlin/so/clix/{models,services}/**/*.kt

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

clix/src/main/kotlin/so/clix/{models,services}/**/*.kt: Use kotlinx.serialization for JSON handling
Map between domain models and DTOs at the boundaries

Files:

  • clix/src/main/kotlin/so/clix/services/TokenService.kt
clix/src/main/kotlin/so/clix/{core,models}/**/*.kt

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Use sealed classes for finite states or results

Files:

  • clix/src/main/kotlin/so/clix/core/Clix.kt
  • clix/src/main/kotlin/so/clix/core/ClixNotification.kt
clix/src/main/kotlin/so/clix/core/**/*.kt

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

clix/src/main/kotlin/so/clix/core/**/*.kt: Use functional error wrappers (sealed classes) in domain logic
Keep domain logic pure and side-effect-free

Files:

  • clix/src/main/kotlin/so/clix/core/Clix.kt
  • clix/src/main/kotlin/so/clix/core/ClixNotification.kt
**/*.gradle.kts

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Use Kotlin 2.x as the minimum Kotlin version (configure Kotlin plugin accordingly)

Files:

  • clix/build.gradle.kts
{build.gradle.kts,settings.gradle.kts,clix/build.gradle.kts,gradle.properties,gradle/wrapper/gradle-wrapper.properties}

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Target Gradle 8.x with Kotlin DSL and JVM 21 toolchain

Files:

  • clix/build.gradle.kts
{clix/build.gradle.kts,clix/src/main/AndroidManifest.xml}

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Set Android minSdk to API 21 or higher

Files:

  • clix/build.gradle.kts
{gradle/libs.versions.toml,**/*.gradle.kts}

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Use Firebase via BOM and version catalog

Files:

  • clix/build.gradle.kts
  • gradle/libs.versions.toml
{gradle/libs.versions.toml,**/*.gradle.kts,detekt.yml}

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Use ktfmt, detekt, and jacoco via the Gradle version catalog

Files:

  • clix/build.gradle.kts
  • gradle/libs.versions.toml
🧠 Learnings (24)
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to {clix/build.gradle.kts,clix/src/main/AndroidManifest.xml} : Set Android minSdk to API 21 or higher

Applied to files:

  • README.md
  • clix/build.gradle.kts
  • gradle/libs.versions.toml
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/** : Follow the specified library source structure under clix/src/main/kotlin/so/clix/(core|models|notification|services|utils)

Applied to files:

  • README.md
  • clix/build.gradle.kts
  • gradle/libs.versions.toml
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/{models,services}/**/*.kt : Use kotlinx.serialization for JSON handling

Applied to files:

  • README.md
  • clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt
  • clix/src/main/kotlin/so/clix/services/TokenService.kt
  • gradle/libs.versions.toml
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/{test,androidTest}/kotlin/**/*.kt : Use JUnit4/Kotest for unit tests and AndroidX Test/Robolectric for instrumentation

Applied to files:

  • README.md
  • clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt
  • gradle/libs.versions.toml
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Use Kotlin Coroutines for asynchronous operations

Applied to files:

  • README.md
  • clix/src/main/kotlin/so/clix/core/Clix.kt
  • clix/build.gradle.kts
  • clix/src/main/kotlin/so/clix/core/ClixNotification.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/services/**/*.kt : Classes interacting with external services must use Service or Repository suffix

Applied to files:

  • README.md
  • clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt
  • clix/src/main/kotlin/so/clix/services/TokenService.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/test/kotlin/so/clix/** : Mirror main source structure for unit tests under clix/src/test/kotlin/so/clix

Applied to files:

  • README.md
  • clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt
  • clix/src/main/kotlin/so/clix/core/Clix.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/models/**/*.kt : Keep domain models serialization-agnostic (no framework annotations in core models)

Applied to files:

  • README.md
  • clix/src/main/kotlin/so/clix/services/TokenService.kt
  • clix/src/main/kotlin/so/clix/core/Clix.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/utils/**/*.kt : Group utility classes/functions logically under utils (and its subpackages)

Applied to files:

  • README.md
  • clix/src/main/kotlin/so/clix/core/Clix.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Do not use service locators or singletons (unless absolutely necessary)

Applied to files:

  • README.md
  • clix/src/main/kotlin/so/clix/core/Clix.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/services/**/*.kt : Handle side effects explicitly within repository/service classes

Applied to files:

  • clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt
  • clix/src/main/kotlin/so/clix/core/Clix.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Use DataStore Preferences for local storage

Applied to files:

  • clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt
  • clix/src/main/kotlin/so/clix/services/TokenService.kt
  • clix/src/main/kotlin/so/clix/core/Clix.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/{test,androidTest}/kotlin/**/*.kt : Use property-based tests for pure functions where applicable

Applied to files:

  • clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/models/**/*.kt : Model types use singular, descriptive names (e.g., User, AuthToken)

Applied to files:

  • clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt
  • clix/src/main/kotlin/so/clix/services/TokenService.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/{models,services}/**/*.kt : Map between domain models and DTOs at the boundaries

Applied to files:

  • clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt
  • clix/src/main/kotlin/so/clix/services/TokenService.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/{test,androidTest}/kotlin/**/*.kt : Use Stub and Spy patterns via MockK for doubles

Applied to files:

  • clix/src/test/kotlin/so/clix/services/TokenServiceTest.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Use descriptive names and prefer expression-style functions where clear

Applied to files:

  • clix/src/main/kotlin/so/clix/services/TokenService.kt
  • clix/src/main/kotlin/so/clix/core/Clix.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Ensure thread safety for shared mutable state

Applied to files:

  • clix/src/main/kotlin/so/clix/core/Clix.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/core/**/*.kt : Keep domain logic pure and side-effect-free

Applied to files:

  • clix/src/main/kotlin/so/clix/core/Clix.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Write small, pure, composable functions; favor immutability and explicit side effects

Applied to files:

  • clix/src/main/kotlin/so/clix/core/Clix.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/{core,models}/**/*.kt : Use sealed classes for finite states or results

Applied to files:

  • clix/src/main/kotlin/so/clix/core/Clix.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to {build.gradle.kts,settings.gradle.kts,clix/build.gradle.kts,gradle.properties,gradle/wrapper/gradle-wrapper.properties} : Target Gradle 8.x with Kotlin DSL and JVM 21 toolchain

Applied to files:

  • clix/build.gradle.kts
  • gradle/libs.versions.toml
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to {gradle/libs.versions.toml,**/*.gradle.kts} : Use Firebase via BOM and version catalog

Applied to files:

  • clix/build.gradle.kts
  • gradle/libs.versions.toml
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Use Jetpack Compose 1.x or Android Views where necessary for UI

Applied to files:

  • gradle/libs.versions.toml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (12)
CHANGELOG.md (1)

7-16: LGTM!

The changelog entry clearly documents the behavioral changes for push notification handlers and the internal naming convention improvements, aligning well with the code changes in this PR.

gradle/libs.versions.toml (2)

19-21: LGTM!

The lifecycle version entry and structure follow the version catalog conventions correctly.


57-58: LGTM!

The androidx-lifecycle-process library is correctly added with proper version reference to enable foreground state detection.

clix/build.gradle.kts (1)

76-76: LGTM!

The lifecycle-process dependency is correctly added to enable ProcessLifecycleOwner for foreground state detection in notification handling.

README.md (1)

22-22: LGTM!

The dependency version is correctly updated to 1.3.2 to match the release.

clix/src/main/kotlin/so/clix/core/ClixNotification.kt (3)

7-8: LGTM!

The imports for Lifecycle and ProcessLifecycleOwner are correctly added to support foreground state detection.


232-261: Well-structured foreground/background handler routing.

The logic correctly routes notifications to the appropriate handler based on app state. Error handling is appropriate: foreground handler failures default to showing the notification, and background handler failures are logged without blocking notification display.


270-277: Code correctly handles cold start edge case; consider adding clarifying comment.

ProcessLifecycleOwner may not be fully initialized when accessed from onMessageReceived() during cold starts. The existing try-catch with fallback to false (background) appropriately handles this scenario—a safe conservative approach that ensures notifications aren't lost.

Adding a brief comment explaining that the exception handling accounts for ProcessLifecycleOwner initialization timing on cold starts would help future maintainers understand this is intentional.

clix/src/main/kotlin/so/clix/core/Clix.kt (4)

40-43: Clean refactoring of internal naming.

The rename from COROUTINE_CONTEXT to coroutineContext follows Kotlin naming conventions for properties. Using a dedicated InitializeLock object is a good practice for identity-based synchronization, making the lock's purpose explicit.


54-54: LGTM!

The coroutineScope correctly references the renamed coroutineContext.


68-68: LGTM!

Using InitializeLock for synchronization is clearer and follows best practices.


266-274: LGTM!

The internal initialize method correctly uses InitializeLock for synchronization and configKey for retrieving saved configuration. The double-checked locking pattern is properly implemented.

…on flow

- Replace hardcoded Clix config values with JSON-based configuration.
- Add `ClixConfig.json.example` for credential setup.
- Update `.gitignore` to exclude sensitive config files.
- Improve modularity of `ClixConfiguration` with JSON parsing.
Copy link
Contributor

@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

🧹 Nitpick comments (3)
samples/basic-app/src/main/kotlin/so/clix/samples/basic/BasicApplication.kt (1)

29-32: Consider adding error handling for configuration initialization.

The ClixConfiguration.initialize(this) call may throw exceptions during JSON parsing or file I/O (e.g., missing ClixConfig.json or invalid JSON format). While this is a sample app, adding error handling would demonstrate best practices and provide better developer experience.

Apply this diff to add error handling:

-        // Initialize ClixConfiguration from JSON file
-        ClixConfiguration.initialize(this)
-
-        Clix.initialize(this, ClixConfiguration.config)
+        // Initialize ClixConfiguration from JSON file
+        try {
+            ClixConfiguration.initialize(this)
+            Clix.initialize(this, ClixConfiguration.config)
+        } catch (e: Exception) {
+            Log.e("BasicApplication", "Failed to initialize configuration", e)
+            // Consider providing fallback configuration or showing user-friendly error
+        }
samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.kt (2)

14-14: Consider documenting the hard-coded DEBUG log level.

The logLevel field is hard-coded to DEBUG and overrides any logLevel value from the JSON configuration (line 25). This might be confusing for developers examining the sample. Consider adding a comment explaining this override behavior.

Apply this diff to add clarifying documentation:

-    private val logLevel: ClixLogLevel = ClixLogLevel.DEBUG
+    // Hard-coded DEBUG level for sample app; overrides JSON config logLevel
+    private val logLevel: ClixLogLevel = ClixLogLevel.DEBUG

19-26: Consider using explicit resource management for asset loading.

While readText() should handle resource cleanup, explicitly using use() would make resource management more explicit and safer.

Apply this diff to use explicit resource management:

     fun initialize(context: Context) {
-        config =
-            json
-                .decodeFromString<ClixConfig>(
-                    context.assets.open("ClixConfig.json").bufferedReader().readText()
-                )
-                .copy(logLevel = logLevel)
+        config = context.assets.open("ClixConfig.json").use { inputStream ->
+            json
+                .decodeFromString<ClixConfig>(
+                    inputStream.bufferedReader().readText()
+                )
+                .copy(logLevel = logLevel)
+        }
     }

Note: Error handling for this initialization is discussed in the BasicApplication.kt review.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7dfa8ae and f2c6242.

📒 Files selected for processing (7)
  • .gitignore (1 hunks)
  • samples/basic-app/README.md (1 hunks)
  • samples/basic-app/build.gradle.kts (2 hunks)
  • samples/basic-app/src/main/assets/ClixConfig.json.example (1 hunks)
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/BasicApplication.kt (1 hunks)
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.kt (1 hunks)
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ContentView.kt (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • samples/basic-app/src/main/assets/ClixConfig.json.example
  • .gitignore
  • samples/basic-app/README.md
🧰 Additional context used
📓 Path-based instructions (4)
samples/**

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Place example applications under samples/

Files:

  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ContentView.kt
  • samples/basic-app/build.gradle.kts
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/BasicApplication.kt
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.kt
**/*.gradle.kts

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Use Kotlin 2.x as the minimum Kotlin version (configure Kotlin plugin accordingly)

Files:

  • samples/basic-app/build.gradle.kts
{gradle/libs.versions.toml,**/*.gradle.kts}

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Use Firebase via BOM and version catalog

Files:

  • samples/basic-app/build.gradle.kts
{gradle/libs.versions.toml,**/*.gradle.kts,detekt.yml}

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Use ktfmt, detekt, and jacoco via the Gradle version catalog

Files:

  • samples/basic-app/build.gradle.kts
🧠 Learnings (21)
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Use descriptive names and prefer expression-style functions where clear

Applied to files:

  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ContentView.kt
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/models/**/*.kt : Define domain models as immutable data classes

Applied to files:

  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ContentView.kt
  • samples/basic-app/build.gradle.kts
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/BasicApplication.kt
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Use DataStore Preferences for local storage

Applied to files:

  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ContentView.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/models/**/*.kt : Keep domain models serialization-agnostic (no framework annotations in core models)

Applied to files:

  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ContentView.kt
  • samples/basic-app/build.gradle.kts
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/BasicApplication.kt
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Write small, pure, composable functions; favor immutability and explicit side effects

Applied to files:

  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ContentView.kt
  • samples/basic-app/build.gradle.kts
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/{models,services}/**/*.kt : Use kotlinx.serialization for JSON handling

Applied to files:

  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ContentView.kt
  • samples/basic-app/build.gradle.kts
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/BasicApplication.kt
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/core/**/*.kt : Keep domain logic pure and side-effect-free

Applied to files:

  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ContentView.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Avoid reflection, annotations, and metaprogramming unless necessary

Applied to files:

  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ContentView.kt
  • samples/basic-app/build.gradle.kts
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to {clix/build.gradle.kts,clix/src/main/AndroidManifest.xml} : Set Android minSdk to API 21 or higher

Applied to files:

  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ContentView.kt
  • samples/basic-app/build.gradle.kts
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/BasicApplication.kt
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Do not use service locators or singletons (unless absolutely necessary)

Applied to files:

  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ContentView.kt
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to {build.gradle.kts,settings.gradle.kts,clix/build.gradle.kts,gradle.properties,gradle/wrapper/gradle-wrapper.properties} : Target Gradle 8.x with Kotlin DSL and JVM 21 toolchain

Applied to files:

  • samples/basic-app/build.gradle.kts
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to {gradle/libs.versions.toml,**/*.gradle.kts,detekt.yml} : Use ktfmt, detekt, and jacoco via the Gradle version catalog

Applied to files:

  • samples/basic-app/build.gradle.kts
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to **/*.gradle.kts : Use Kotlin 2.x as the minimum Kotlin version (configure Kotlin plugin accordingly)

Applied to files:

  • samples/basic-app/build.gradle.kts
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/{test,androidTest}/kotlin/**/*.kt : Use JUnit4/Kotest for unit tests and AndroidX Test/Robolectric for instrumentation

Applied to files:

  • samples/basic-app/build.gradle.kts
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to {gradle/libs.versions.toml,**/*.gradle.kts} : Use Firebase via BOM and version catalog

Applied to files:

  • samples/basic-app/build.gradle.kts
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/** : Follow the specified library source structure under clix/src/main/kotlin/so/clix/(core|models|notification|services|utils)

Applied to files:

  • samples/basic-app/build.gradle.kts
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Use Kotlin Coroutines for asynchronous operations

Applied to files:

  • samples/basic-app/build.gradle.kts
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/test/kotlin/so/clix/** : Mirror main source structure for unit tests under clix/src/test/kotlin/so/clix

Applied to files:

  • samples/basic-app/build.gradle.kts
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/BasicApplication.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/utils/**/*.kt : Group utility classes/functions logically under utils (and its subpackages)

Applied to files:

  • samples/basic-app/build.gradle.kts
  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/{models,services}/**/*.kt : Map between domain models and DTOs at the boundaries

Applied to files:

  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.kt
📚 Learning: 2025-10-15T05:36:01.516Z
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Order declarations Public → Internal → Private

Applied to files:

  • samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.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). (1)
  • GitHub Check: build
🔇 Additional comments (5)
samples/basic-app/build.gradle.kts (2)

48-48: LGTM!

The kotlinx.serialization.json dependency is correctly added via the version catalog and aligns with the project's JSON handling requirements.


4-4: Upgrade Kotlin version to 2.x minimum as required by coding guidelines.

The Kotlin version in gradle/libs.versions.toml is set to 1.9.25, which does not meet the required minimum of Kotlin 2.x for **/*.gradle.kts files. Update the version catalog accordingly, which will also update the kotlin-serialization plugin since it references the Kotlin version.

⛔ Skipped due to learnings
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to **/*.gradle.kts : Use Kotlin 2.x as the minimum Kotlin version (configure Kotlin plugin accordingly)
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to {gradle/libs.versions.toml,**/*.gradle.kts,detekt.yml} : Use ktfmt, detekt, and jacoco via the Gradle version catalog
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/{models,services}/**/*.kt : Use kotlinx.serialization for JSON handling
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to {build.gradle.kts,settings.gradle.kts,clix/build.gradle.kts,gradle.properties,gradle/wrapper/gradle-wrapper.properties} : Target Gradle 8.x with Kotlin DSL and JVM 21 toolchain
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/so/clix/models/**/*.kt : Keep domain models serialization-agnostic (no framework annotations in core models)
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to {gradle/libs.versions.toml,**/*.gradle.kts} : Use Firebase via BOM and version catalog
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : Avoid reflection, annotations, and metaprogramming unless necessary
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to {clix/build.gradle.kts,clix/src/main/AndroidManifest.xml} : Set Android minSdk to API 21 or higher
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/{test,androidTest}/kotlin/**/*.kt : Use JUnit4/Kotest for unit tests and AndroidX Test/Robolectric for instrumentation
Learnt from: CR
Repo: clix-so/clix-android-sdk PR: 0
File: .cursor/rules/guidelines.mdc:0-0
Timestamp: 2025-10-15T05:36:01.516Z
Learning: Applies to clix/src/main/kotlin/**/*.kt : No reflection under any circumstances
samples/basic-app/src/main/kotlin/so/clix/samples/basic/ContentView.kt (1)

116-116: LGTM!

The migration from static constants to property-based configuration access is clean and correct. The initialization order is safe since ClixConfiguration.initialize(context) is called in BasicApplication.onCreate before the UI is composed.

Also applies to: 120-120

samples/basic-app/src/main/kotlin/so/clix/samples/basic/ClixConfiguration.kt (2)

9-12: LGTM!

The Json configuration is appropriate for loading configuration files. The ignoreUnknownKeys = true setting enables forward compatibility, and isLenient = true provides flexibility for the sample app.


16-17: LGTM!

The lateinit var with private setter is appropriate for deferred initialization. The initialization order ensures this property is set before any external access.

@pitzcarraldo pitzcarraldo merged commit 18f55d0 into main Dec 17, 2025
3 checks passed
@pitzcarraldo pitzcarraldo deleted the feat/push-lifecycle branch December 17, 2025 04:55
@coderabbitai coderabbitai bot mentioned this pull request Feb 11, 2026
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.

1 participant