Skip to content

feat: Migrate networking to Ktor and enhance multiplatform support#4890

Merged
jamesarich merged 12 commits intomainfrom
feat/unify-imageloaders
Mar 23, 2026
Merged

feat: Migrate networking to Ktor and enhance multiplatform support#4890
jamesarich merged 12 commits intomainfrom
feat/unify-imageloaders

Conversation

@jamesarich
Copy link
Copy Markdown
Collaborator

This pull request makes significant changes to the project's networking and image loading infrastructure, migrating from OkHttp to pure Ktor for all HTTP networking, and adopting Coil's Ktor-based fetcher for image loading. It also removes OkHttp dependencies and related configuration across modules, updates dependency injection, and adjusts build logic to reflect these changes. Additionally, there are improvements to test configuration and dependency management for multiplatform modules.

Networking and Image Loading Modernization:

  • Migrated all networking from OkHttp to Ktor, using ktor-client-android for Android and ktor-client-java for desktop/JVM, and replaced OkHttp logging with Ktor's Logging plugin. This includes providing HttpClient via Koin and removing OkHttp from dependency injection modules and build files. [1] [2] [3] [4] [5]
  • Switched image loading to use coil-network-ktor3 and KtorNetworkFetcherFactory on all platforms, configuring ImageLoader only in host modules and ensuring feature modules depend only on libs.coil for AsyncImage. Updated MainActivity to bridge Koin-provided ImageLoader to Coil's singleton. [1] [2] [3] [4] [5]

Dependency Cleanup and Refactoring:

  • Removed all OkHttp and related logging interceptor dependencies from build files, dependency injection modules, and test modules. Also removed Datadog OkHttp integration for Google builds. [1] [2] [3] [4] [5]
  • Updated ProGuard rules to remove OkHttp-specific entries and clarify networking-related keep rules.

Multiplatform and Dependency Management:

  • Consolidated Room/SQLite dependencies for Android and JVM into a shared jvmAndroidMain source set in core:data, improving multiplatform code sharing and reducing duplication.
  • Updated navigation dependencies to use only the UI module of JetBrains Navigation3 in multiplatform modules.

Build Logic and Test Improvements:

  • Added a new configureTestOptions function to the build logic to allow modules with no discovered tests to pass without failing the build, and parallelized unit tests for better CI performance. [1] [2] [3]
  • Changed Compose UI tooling dependency to be debugImplementation only, avoiding unnecessary inclusion in release builds.

Documentation Updates:

  • Updated project documentation to reflect the migration to Ktor for networking and Coil's Ktor fetcher for image loading, clarifying dependency usage and patterns for multiplatform development.

These changes modernize the codebase, streamline dependencies, and improve consistency across platforms.

This commit migrates the Coil image loading configuration from OkHttp to Ktor 3 across the project and introduces a singleton `ImageLoader` setup for both Android and Desktop platforms. This transition aligns with the project's move toward Kotlin Multiplatform (KMP).

Specific changes include:
- **Coil & Ktor Migration**:
    - Replaced `coil-network-okhttp` with `coil-network-ktor3` in `libs.versions.toml`.
    - Updated `NetworkModule` (Android) to use `KtorNetworkFetcherFactory` and `HttpClient` instead of `OkHttpNetworkFetcherFactory`.
    - Simplified dependency declarations in `app`, `core:network`, and various feature modules, removing redundant `coil` or `okhttp` references where possible.
- **Desktop Enhancements**:
    - Added Coil dependencies (`coil`, `coil-network-ktor3`, `coil-svg`) to the `desktop` module.
    - Implemented a custom `ImageLoader` factory in the desktop `Main.kt` with SVG support, Ktor networking, and local disk/memory caching.
    - Introduced keyboard shortcuts (Cmd/Meta + Key) for Quit, Settings, Theme toggle, and navigation to top-level destinations (Conversations, Nodes, Map, Connections, About).
    - Added `classpathPainterResource` to handle image loading from resources on the desktop JVM target.
    - Implemented `navigateTopLevel` to manage the desktop navigation backstack.
- **Android Integration**:
    - Updated `MainActivity` to bridge the Koin-provided `ImageLoader` to Coil's singleton via `setSingletonImageLoaderFactory`.

Signed-off-by: James Rich <[email protected]>
This commit migrates the networking layer from OkHttp to the Ktor Android engine across the project. This simplifies the dependency graph by removing OkHttp-specific interceptors and logging in favor of Ktor's native plugins.

Specific changes include:
- **Dependency Updates**: Removed `okhttp`, `okhttp3-logging-interceptor`, and `dd-sdk-android-okhttp` from the version catalog and build files.
- **Engine Migration**: Replaced `ktor-client-okhttp` with `ktor-client-android` and updated `HttpClient` providers to use the `Android` engine instead of `OkHttp`.
- **Logging**: Switched from OkHttp's `HttpLoggingInterceptor` to the Ktor `Logging` plugin for debug builds.
- **Module Cleanup**:
    - Simplified `FDroidNetworkModule` and `GoogleNetworkModule` by removing manual `OkHttpClient` bean definitions and cache configurations.
    - Removed `DatadogInterceptor` and `DatadogEventListener` configurations.
- **Testing**: Updated `KoinVerificationTest` to remove `OkHttpClient` from the expected dependency graph.
- **Documentation**: Updated `AGENTS.md` to reflect the architectural decision to use pure Ktor for networking.

Signed-off-by: James Rich <[email protected]>
…ndencies

This commit refactors the network module to streamline dependency management and remove redundant platform-specific configurations. The `HttpClient` provision was removed from the Android-specific Koin module in favor of a more unified approach.

Specific changes include:
- **Dependency Cleanup**: Removed `libs.ktor.client.android` from `core:network` build configuration.
- **DI Refactoring**: Removed `provideHttpClient` from `CoreNetworkAndroidModule`, shifting away from the platform-specific Ktor Android engine configuration within that module.
- **ProGuard**: Cleaned up networking-related ProGuard rules, removing redundant `okhttp3` warnings.
- **Maintenance**: Deleted `googleReleaseRuntimeClasspath.txt` dependency snapshot.

Signed-off-by: James Rich <[email protected]>
This commit removes redundant and unused dependencies across several modules to streamline the build configuration and reduce potential classpath conflicts.

Specific changes include:
- **desktop**: Removed explicit `ktor-client-core` dependency as it is transitively included by `ktor-client-java`.
- **feature:node**: Removed redundant Material 2 Vico dependency and cleaned up duplicate markdown renderer declarations in `androidMain`.
- **feature:intro**: Removed `navigation3-ui` from `androidMain`.
- **feature:settings**: Removed duplicate markdown renderer dependencies in `androidMain`.
- **core:common**: Removed `aboutlibraries` dependencies.

Signed-off-by: James Rich <[email protected]>
This commit cleans up Navigation 3 dependency declarations by standardizing on `navigation3-ui` and removing the redundant `navigation3-runtime` alias from the version catalog and module build files.

Specific changes include:
- **Version Catalog**: Removed `jetbrains-navigation3-runtime` from `libs.versions.toml` as it was a duplicate entry pointing to the same Maven coordinates as `jetbrains-navigation3-ui`.
- **Dependency Migration**: Updated `core:navigation`, `app`, and several feature modules (`node`, `intro`, `messaging`, `connections`, `map`, `settings`, `firmware`) to use `libs.jetbrains.navigation3.ui` exclusively.
- **Dependency Cleanup**:
    - Removed unused `core.common` dependency from `feature:map`.
    - Added `kotlinx.collections.immutable` to `feature:map`.
    - Cleaned up redundant navigation imports in `feature:settings`, `feature:map`, `feature:firmware`, and the `app` module.

Signed-off-by: James Rich <[email protected]>
…roid and JVM

This commit refactors the build configuration for the `core:data` module to reduce duplication by grouping shared Room and SQLite dependencies into a common source set for Android and JVM targets.

Specific changes include:
- Applied the `meshtastic.kmp.jvm.android` plugin.
- Introduced a `jvmAndroidMain` source set to manage dependencies shared between Android and Desktop JVM targets.
- Moved `androidx.room.runtime`, `androidx.room.paging`, and `androidx.sqlite.bundled` from separate `androidMain` and `jvmMain` blocks into the unified `jvmAndroidMain` configuration.

Signed-off-by: James Rich <[email protected]>
This commit relocates several dependencies in the firmware feature module from the Android-specific source set to `commonMain` to support better code sharing and multiplatform compatibility. It also includes a minor cleanup in the BLE core module.

Specific changes include:
- Moved `coil`, `markdown-renderer`, and `markdown-renderer-m3` from `androidMain` to `commonMain` in `feature/firmware/build.gradle.kts`.
- Removed an empty, unused `jvmMain.dependencies` block from `core/ble/build.gradle.kts`.

Signed-off-by: James Rich <[email protected]>
This commit refactors build-logic conventions and cleans up unused dependencies and properties to streamline the build process. Key changes include consolidating test configurations into `ProjectExtensions.kt` and removing deprecated plugins and experimental flags.

Specific changes include:
- **Build Logic**:
    - Moved `failOnNoMatchingTests` configuration from the root `build.gradle.kts` to `ProjectExtensions.kt`.
    - Integrated `configureTestOptions()` into `KmpLibraryConventionPlugin`.
    - Corrected `androidx-compose-ui-tooling` to use `debugImplementation` only.
- **Dependency Cleanup**:
    - Removed `vico-compose-m2`, `firebase-perf`, and `dependency-guard` from `libs.versions.toml`.
    - Removed the `meshtastic-android-test` plugin definition.
- **Properties & Config**:
    - Removed several Android and KSP properties from `gradle.properties`, including `android.enableJetifier`, `android.useAndroidX`, and `ksp.useKSP2`.
    - Cleaned up redundant whitespace and plugin aliases in the root `build.gradle.kts`.

Signed-off-by: James Rich <[email protected]>
@github-actions github-actions bot added the enhancement New feature or request label Mar 23, 2026
… shortcuts

This commit updates `docs/roadmap.md` to align with recent changes to the desktop implementation, specifically the removal of the native MenuBar in favor of keyboard shortcuts.

Specific changes include:
- Updated the "Last updated" date to 2026-03-23.
- Updated Tier 2 Polish priorities to reflect that MenuBar integration has been removed and replaced by keyboard shortcuts via `onPreviewKeyEvent`.
- Updated the Desktop Platform Status table to list specific supported keyboard shortcuts (⌘Q, ⌘,, ⌘⇧T, ⌘1-4, ⌘/) as the replacement for the native application menu bar.

Signed-off-by: James Rich <[email protected]>
This commit updates the copyright headers to include 2026 and applies project-wide code formatting and linting rules to the build-logic convention plugins.

Specific changes include:
- Updated copyright headers to `2025-2026 Meshtastic LLC` across convention plugin files.
- Applied `ktfmt` with a 120-character maximum width across `build-logic`.
- Refactored `KotlinAndroid.kt` to support a `warningsAsErrors` Gradle property, defaulting to `false`.
- Updated `Kover.kt` filters to exclude iOS compile-only stubs (`*NoopStubs*`).
- Removed `java.time.*` from `compose_compiler_config.conf`.
- Removed an unnecessary `afterEvaluate` block in `FlavorResolution.kt` to improve configuration performance.
- Consolidated various one-line lambda expressions and cleaned up redundant imports and whitespace.
- Updated `Graph.kt` to improve compatibility with Gradle Isolated Projects.

Signed-off-by: James Rich <[email protected]>
…lution

This commit replaces the legacy `afterEvaluate` approach of stamping attributes on every resolvable Android configuration with Gradle `AttributeDisambiguationRule`s. This ensures robust flavor selection when a consumer (e.g., a KMP module's host test) does not specify a marketplace attribute but the producer publishes multiple variants.

This change improves compatibility with Configuration Cache and Isolated Projects by moving resolution logic from configuration time to dependency resolution time.

Specific changes include:
- Introduced `ProductFlavorDisambiguationRule` and `StringDisambiguationRule` to handle flavor selection during variant-aware resolution.
- Updated `configureAndroidMarketplaceFallback` to register these rules in the `attributesSchema` for both `ProductFlavorAttr` and the legacy "marketplace" string attribute.
- Removed the manual configuration-looping logic (`configurations.configureEach`) that previously attempted to infer flavors from configuration names.
- Maintained support for the `meshtastic.defaultMarketplace` Gradle property to control the default fallback flavor.

Signed-off-by: James Rich <[email protected]>
…cies

This commit updates the build logic to prevent build failures when no tests are discovered and adds necessary UI dependencies to the widget feature module.

Specific changes include:
- **Build Logic**: Configured `AbstractTestTask` to set `failOnNoDiscoveredTests` to `false`. This prevents Gradle 9+ from failing builds in modules where tests might be present but are currently commented out or not yet implemented.
- **Widget Feature**: Added `androidx.compose.ui` dependency to `feature:widget` to support the use of `LocalConfiguration` and `LocalDensity`.

Signed-off-by: James Rich <[email protected]>
@jamesarich jamesarich added this pull request to the merge queue Mar 23, 2026
Merged via the queue into main with commit b3b38ac Mar 23, 2026
7 checks passed
@jamesarich jamesarich deleted the feat/unify-imageloaders branch March 23, 2026 16:58
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.

1 participant