Skip to content

refactor: migrate core modules to Kotlin Multiplatform and consolidat…#4735

Merged
jamesarich merged 2 commits intomainfrom
feat/kmp-core-migration
Mar 6, 2026
Merged

refactor: migrate core modules to Kotlin Multiplatform and consolidat…#4735
jamesarich merged 2 commits intomainfrom
feat/kmp-core-migration

Conversation

@jamesarich
Copy link
Copy Markdown
Collaborator

…e DI

  • Convert core:data, core:network, core:domain, core:di, and core:prefs into Kotlin Multiplatform (KMP) modules.
  • Delete the :core:analytics module and move flavor-specific implementations (Google/Firebase and F-Droid) directly into the :app module.
  • Relocate the PlatformAnalytics interface and DataPair model to core:repository.
  • Move platform-specific dependency injection (Hilt) modules for network and analytics from library modules to the :app module.
  • Update core:domain use cases to use okio (BufferedSink, BufferedSource) instead of java.io to support non-Android targets.
  • Refactor NodeManagerImpl to use atomicfu and kotlinx-collections-immutable for concurrency in shared code.
  • Update PacketHandlerImpl and MeshMessageProcessorImpl to use Mutex and KMP-compatible collection types.
  • Migrate the application package from com.geeksville.mesh to org.meshtastic.app.
  • Introduce expect/actual patterns for Location and LocationRepository to support platform-independent location handling.
  • Update ExportDataUseCase to use kotlinx-datetime for timestamp formatting.

…e DI

- Convert `core:data`, `core:network`, `core:domain`, `core:di`, and `core:prefs` into Kotlin Multiplatform (KMP) modules.
- Delete the `:core:analytics` module and move flavor-specific implementations (Google/Firebase and F-Droid) directly into the `:app` module.
- Relocate the `PlatformAnalytics` interface and `DataPair` model to `core:repository`.
- Move platform-specific dependency injection (Hilt) modules for network and analytics from library modules to the `:app` module.
- Update `core:domain` use cases to use `okio` (`BufferedSink`, `BufferedSource`) instead of `java.io` to support non-Android targets.
- Refactor `NodeManagerImpl` to use `atomicfu` and `kotlinx-collections-immutable` for concurrency in shared code.
- Update `PacketHandlerImpl` and `MeshMessageProcessorImpl` to use `Mutex` and KMP-compatible collection types.
- Migrate the application package from `com.geeksville.mesh` to `org.meshtastic.app`.
- Introduce `expect`/`actual` patterns for `Location` and `LocationRepository` to support platform-independent location handling.
- Update `ExportDataUseCase` to use `kotlinx-datetime` for timestamp formatting.

Signed-off-by: James Rich <[email protected]>
@github-actions github-actions bot added the enhancement New feature or request label Mar 6, 2026
@jamesarich jamesarich requested a review from Copilot March 6, 2026 19:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates core modules (core:data, core:network, core:domain, core:di, core:prefs) to Kotlin Multiplatform (KMP), deletes the core:analytics module (moving its interfaces to core:repository and implementations to the app module), migrates the application package from com.geeksville.mesh to org.meshtastic.app, and switches domain use cases from java.io to okio for cross-platform compatibility.

Changes:

  • Converted core modules to KMP with expect/actual patterns (e.g., Location), migrated tests from JUnit to kotlin.test, and replaced java.io with okio in domain use cases.
  • Deleted the core:analytics module, relocated PlatformAnalytics and DataPair to core:repository, and moved flavor-specific analytics/network DI modules into the app module.
  • Migrated the application package from com.geeksville.mesh to org.meshtastic.app across all app-level files including AndroidManifest.xml, services, receivers, navigation, and widgets.

Reviewed changes

Copilot reviewed 205 out of 265 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
settings.gradle.kts Removes :core:analytics module
gradle/libs.versions.toml Adds kotlinx-atomicfu dependency
core/analytics/* Deleted module (build.gradle.kts, README.md)
core/repository/src/commonMain/.../PlatformAnalytics.kt Relocated from analytics, removed AddNavigationTrackingEffect
core/repository/src/commonMain/.../DataPair.kt Relocated from analytics module
core/repository/src/commonMain/.../LocationRepository.kt New expect/actual pattern for KMP location
core/repository/src/androidMain/.../Location.kt Android actual typealias for Location
core/di/build.gradle.kts Converted to KMP library
core/domain/build.gradle.kts Converted to KMP library with okio/kotlinx-datetime
core/domain/src/commonMain/.../*.kt New/migrated use cases using okio types
core/domain/src/commonTest/.../*.kt Tests migrated from JUnit to kotlin.test
core/network/build.gradle.kts Converted to KMP with marketplace attribute hack
core/network/src/main/AndroidManifest.xml Deleted (INTERNET permission removed)
core/network/.../MQTTRepository.kt New interface extracted from impl
core/network/.../MQTTRepositoryImpl.kt Implements new MQTTRepository interface
core/prefs/build.gradle.kts Converted to KMP library
core/prefs/src/commonMain/.../*.kt New prefs implementations and DI qualifiers
core/data/src/commonMain/.../*.kt Updated imports, new data sources & interfaces
feature/map/.../*.kt Relocated CustomTileProvider, GoogleMapsPrefs to feature:map
feature/settings/.../RadioConfigViewModel.kt Updated to use okio wrappers
feature/settings/.../SettingsViewModel.kt Updated to use okio BufferedSink
app/build.gradle.kts Updated namespace, added dependencies, removed analytics
app/src/main/AndroidManifest.xml Updated all class references to new package
app/src/main/kotlin/org/meshtastic/app/**/*.kt Package migration from com.geeksville.mesh
app/src/{google,fdroid}/.../*.kt Moved analytics/network DI modules to app
Comments suppressed due to low confidence (3)

core/domain/src/commonMain/kotlin/org/meshtastic/core/domain/usecase/settings/ExportSecurityConfigUseCase.kt:48

  • The ExportSecurityConfigUseCase previously formatted the JSON output with JSON_INDENT_SPACES = 4 (pretty printing). The new implementation uses buildJsonObject { ... }.toString() which produces compact/minified JSON by default. This is a behavioral change that may affect readability of exported security config files for end users. If the pretty-printed format was intentional for user-facing exports, consider using Json { prettyPrint = true }.encodeToString(JsonElement.serializer(), jsonObject) instead.
    core/repository/src/commonMain/kotlin/org/meshtastic/core/repository/PlatformAnalytics.kt:34
  • The AddNavigationTrackingEffect method was removed from the PlatformAnalytics interface and all its implementations, and the call was removed from MainScreen. However, for the Google flavor, this means Firebase/Datadog screen tracking will no longer work. If navigation tracking was intentional for the Google flavor, this functionality should be re-implemented elsewhere (e.g., directly in the MainActivity or in a separate navigation tracking component).
    feature/map/src/google/kotlin/org/meshtastic/feature/map/prefs/di/GoogleMapsModule.kt:43
  • The GoogleMapsDataStore annotation was changed from internal to public. While this may have been necessary to allow access from the feature:map module after relocation, it broadens the API surface unnecessarily. Consider whether a narrower visibility is possible, or document why this change was needed.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +59 to 63
configurations.all {
if (name.contains("android", ignoreCase = true)) {
attributes.attribute(marketplaceAttr, "fdroid")
}
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The core:network build.gradle.kts hardcodes the marketplace attribute to "fdroid" for all Android configurations. This means the Google flavor's dependencies (like DataDog OkHttp integration, which was previously added via googleImplementation) won't be picked up correctly for the network module. Since the DataDog OkHttp dependency has been moved to the app module, this may be intentional, but it could also cause issues if any network module code conditionally depends on flavor-specific behavior.

Copilot uses AI. Check for mistakes.
val intent =
android.content.Intent().apply {
setClassName("com.geeksville.mesh", "com.geeksville.mesh.service.MeshService")
setClassName("com.geeksville.mesh", "org.meshtastic.app.service.MeshService")
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The setClassName call uses the old application ID "com.geeksville.mesh" as the package name (first parameter), but the service class name has been updated to "org.meshtastic.app.service.MeshService". If the application ID has also been migrated to org.meshtastic.app (as suggested by app/build.gradle.kts setting namespace = "org.meshtastic.app"), then the first parameter should also be updated. However, the applicationId is set via config.properties and may still be com.geeksville.mesh for backward compatibility. Please verify that the applicationId (not namespace) still matches "com.geeksville.mesh" — otherwise this setClassName call will fail to find the service.

Copilot uses AI. Check for mistakes.
} else {
Log.w(TAG, "No service found for action com.geeksville.mesh.Service. Falling back to default.")
intent.setClassName("com.geeksville.mesh", "com.geeksville.mesh.service.MeshService")
intent.setClassName("com.geeksville.mesh", "org.meshtastic.app.service.MeshService")
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

Same concern as AndroidRadioControllerImpl.kt: the first parameter "com.geeksville.mesh" is the application ID used to locate the service component. The service class has been renamed to "org.meshtastic.app.service.MeshService", but the package name must match the actual applicationId. If the applicationId is still com.geeksville.mesh, this is fine. If it has changed, this will break.

Copilot uses AI. Check for mistakes.
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 6, 2026

Codecov Report

❌ Patch coverage is 0% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 0.00%. Comparing base (9daafa9) to head (99eb3fb).
⚠️ Report is 4 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...htastic/android/meshserviceexample/MainActivity.kt 0.00% 1 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff          @@
##            main   #4735   +/-   ##
=====================================
  Coverage   0.00%   0.00%           
=====================================
  Files          3       3           
  Lines        231     231           
  Branches      34      34           
=====================================
  Misses       231     231           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Update `AndroidRadioInterfaceService` to observe device address changes via a Flow, ensuring the radio interface restarts automatically when the address is updated. This change also removes emulator-specific logic that previously defaulted to a mock interface.

- AndroidRadioInterfaceService.kt: Added flow collector for `radioPrefs.devAddr` in `initListeners`
- Removed `shouldDefaultToMockInterface` and `BuildUtils` dependency
- Simplified `getDeviceAddress()` to return the current value from `_currentDeviceAddressFlow`
@jamesarich jamesarich added this pull request to the merge queue Mar 6, 2026
Merged via the queue into main with commit cffbd08 Mar 6, 2026
6 checks passed
@jamesarich jamesarich deleted the feat/kmp-core-migration branch March 6, 2026 22:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants