Files
Meshtastic-Android/feature/map
James Rich cf97f2d5cd refactor(map): polish — DRY coordinate helpers, tighter visibility, dead code removal, null safety
- Extract toGeoPositionOrNull() into MapConstants.kt, replacing 8 duplicated
  coordinate-conversion patterns across GeoJsonConverters, TracerouteLayers,
  TracerouteMap, NodeTrackMap, InlineMap, and MapScreen
- Extract typedFeatureCollection() helper to centralize the single unavoidable
  UNCHECKED_CAST, eliminating 9 scattered @Suppress annotations
- Fix hardcoded style URI in InlineMap — now uses MapStyle.OpenStreetMap.toBaseStyle()
- Tighten visibility: internal on MapButton, NodeTrackLayers, TracerouteLayers;
  private on BaseMapViewModel.nodes
- Fix null safety: replace waypoint!!.id with safe mapNotNull pattern
- Remove dead code: getUser(), myId (BaseMapViewModel); mapStyleId, applicationId,
  setDestNum, mapPrefs (NodeMapViewModel)
- Remove redundant empty onFrame={} in MaplibreMapContent
- Rename COORDINATE_PRECISION to FORMAT_DECIMAL_FACTOR in EditWaypointDialog
- Update stale KDoc on BaseMapViewModel and MapButton; add KDoc on FeatureMapModule,
  LayerType, MapLayerItem, MapNavigation.mapGraph
- Add 11 new tests: toGeoPositionOrNull (4), typedFeatureCollection (1),
  convertIntToEmoji fallback (1), combined filters (1), MapStyle.toBaseStyle (3),
  MapStyle defaults (1)
2026-04-14 22:30:42 -05:00
..

:feature:map

Overview

The :feature:map module provides the mapping interface for the application. Map rendering is decomposed into three focused CompositionLocal provider contracts, each with per-flavor implementations in :app.

Architecture

Provider Contracts (in core:ui/commonMain)

Contract Purpose Implementations
MapViewProvider Main map (nodes, waypoints, controls) GoogleMapViewProvider, FdroidMapViewProvider
NodeTrackMapProvider Per-node GPS track overlay (embedded in PositionLogScreen) Google: NodeTrackMapMapView(GoogleMapMode.NodeTrack), F-Droid: NodeTrackMapNodeTrackOsmMap
TracerouteMapProvider Traceroute route visualization Google: TracerouteMapMapView(GoogleMapMode.Traceroute), F-Droid: TracerouteMapTracerouteOsmMap

All providers are injected via CompositionLocal in MainActivity.kt and consumed by feature modules without direct dependency on Google Maps or osmdroid.

Shared ViewModels (in commonMain)

  • BaseMapViewModel — Core contract for all map state management, node markers, camera positions, and traceroute node selection logic (TracerouteNodeSelection, tracerouteNodeSelection()).
  • NodeMapViewModel — Shared logic for per-node map views (track display, position history).

Key Data Types

  • TracerouteOverlay (core:model/commonMain) — Pure data class representing traceroute route segments. Extracted from feature:map for cross-module reuse.
  • TracerouteNodeSelection (feature:map/commonMain) — Data class modeling node selection results during traceroute visualization.
  • GeoConstants (core:model/commonMain) — Centralized geographic constants (DEG_D, HEADING_DEG, EARTH_RADIUS_METERS).

Map Providers

  • Google Maps (google flavor): Uses Google Play Services Maps SDK. Implementations in app/src/google/kotlin/org/meshtastic/app/map/.
  • OpenStreetMap (fdroid flavor): Uses osmdroid for a fully open-source experience. Implementations in app/src/fdroid/kotlin/org/meshtastic/app/map/.

Features

  • Live Node Tracking: Real-time position updates for nodes on the mesh.
  • Waypoints: Create and share points of interest.
  • Per-Node Track Overlay: Embedded map in PositionLogScreen showing a node's GPS track history.
  • Traceroute Visualization: Dedicated map view showing route segments between mesh nodes.
  • Offline Maps: Support for pre-downloaded map tiles (via osmdroid).

Module dependency graph

graph TB
  :feature:map[map]:::kmp-feature

classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000;
classDef android-application-compose fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000;
classDef compose-desktop-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000;
classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000;
classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000;
classDef android-library-compose fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000;
classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000;
classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000;
classDef kmp-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000;
classDef kmp-library-compose fill:#FFC1CC,stroke:#000,stroke-width:2px,color:#000;
classDef kmp-library fill:#FFC1CC,stroke:#000,stroke-width:2px,color:#000;
classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000;