Skip to content

Releases: jhotadhari/react-native-mapsforge-vtm

v0.9.0

Choose a tag to compare

@jhotadhari jhotadhari released this 24 Sep 15:10

Added

  • Scene-based layer ordering — the cursor-chain / LayerOrderRegistry architecture is replaced by a scene model: LayerScene (single source of truth, commit-phase mutations, immutable plan()) + SceneSync (debounced walk + single-flight reorderLayers/applyEntryPriorities). Order is a function of committed state, derived from an anchor walk over the committed view tree.
  • LayerStackController — native absolute-plan applier (MapMutationQueue-serialized) with a post-apply self-check surfaced in getDebugLayerDump() (appliedMatchesExpected, expectedUuids, appliedUuids, notInPlanCount).
  • Deterministic fragment keys — frag:<owner>:<type> (SharedLayer/LayerMarker) and run:<anchor> (implicit type-runs).
  • useSceneBusy() — reactive hook (exported) signalling that the layer-scene presenter has pending/in-flight ordering work (walk, sync, entry-priority commits, or unapplied mutations). Consumers can wire it to a loading indicator; re-renders only on true↔false transitions.
  • SceneSync.subscribeBusy() / isBusy() — busy subscription for the scene presenter.
  • Shared-layer extension hooks — useSceneFragmentUuid (standalone type-run fragment key), useSceneFragmentReady (grouped-entry readiness gate), and the fragmentUuidFor / runUuidFor deterministic identity builders, exported for third-party shared-fragment layer types.
  • updateLayers batch API — LayerPath geometry/paint updates collapse into one native updateLayers call per frame (per-entry updateCoordinates batching), removing the per-line bridge churn on bulk re-render (e.g. zoom re-simplification).

Changed

  • Fragment UUID scheme — shared-layer fragment UUIDs changed from __vtm_shared_<type>__<index> to frag:<owner>:<type> / run:<anchor>. Any code keying on the old strings must update.
  • Create-phase performance — planWithResolved is now memoized per fragment/type-run, and LayerScene batches listener notification into one microtask flush, collapsing the many-entry create phase from O(N²) to ~O(N log N).

Removed

  • useLayerOrder / createLayerOrderRegistry / LayerOrderRegistry — replaced by useLayerAnchor, useLayerEntry, useSceneUuidBinding, LayerScene, and SceneSync (all exported from src/index.tsx).
  • Create-time positionIndex — the positionIndex param is no longer sent to native createLayer/createMarker. Within-fragment order is now applied via applyEntryPriorities using sparse priorities from PriorityAllocator.
  • Synchronous LayerHelper.addLayer / removeLayer — deleted; use addLayerAsync / removeLayerAsync (the only layer-mutation API).
  • SceneCommand / commandLog() — the replayable command log was removed; LayerScene.version() is the mutation signal.

v0.8.3

Choose a tag to compare

@jhotadhari jhotadhari released this 09 Aug 15:13

Fixed

  • Yalc self-reference — package.json accidentally included "react-native-mapsforge-vtm": "file:.yalc/..." as a dependency of itself, making the npm tarball unresolvable. Self-reference removed and library unregistered from its own yalc installations.

v0.8.2

Choose a tag to compare

@jhotadhari jhotadhari released this 09 Aug 14:48

Changed

  • useNativeLayerLifecycle — calls registry.markNativeDirty() after every createLayer/removeLayer resolution.

Fixed

  • reorderMinimalMoves — first-element insertion before vtm-internal layers. When the first element of orderedLayers is not in the LIS and afterLayer is null, the code previously inserted at index 0 — before vtm-internal layers (GestureLayer, EventLayer). Now scans for the first JS-managed layer and inserts before it.
  • Concurrent reorderLayers calls — flush() now uses an isReordering flag to serialize async reorderLayers calls, preventing overlapping snapshot subtractions that could produce negative nativeDirtyCount values or out-of-order .then() callbacks overwriting lastAppliedUuids.
  • ReindexScope — Phase 2 sentinel placement now uses priority-based ordering (matching Phase 1), and scheduleSync is always called after a children → sentinel transition.
  • Layer‑order drift after native create/remove — flush() hardened against failed reorderLayers calls (flags now set in .then()) and native z‑order drift from create/remove within unchanged SharedLayer fragments (nativeDirtyCount counter, useLayerOrder guard updated).

v0.8.1

Choose a tag to compare

@jhotadhari jhotadhari released this 08 Aug 16:11

Removed

  • LineBucket.java + RenderBuckets.java — redundant source copies
    that duplicated classes already present in the vtm 0.29.0 JAR. They were
    added as a workaround for a claimed "D8 drops them" behavior that was
    actually a stale-build artifact. On clean builds (verified with a wiped
    Gradle cache) the JAR's classes reach the APK correctly without the
    source copies. Removing them eliminates the duplicate-class potential
    for apps that use the library without an extension.

Fixed

  • strip-vtm-classes.gradle — JAR paths captured too early on CI. On a
    fresh Gradle cache (CI), the vtm JAR hasn't been downloaded yet during
    Gradle's configuration phase (projectsEvaluated), so the cache walk
    returned an empty set and the strip task skipped patching. The unpatched
    JAR's LineBucket/RenderBuckets then collided with the extension's
    shadowed copies at DEX merge (Type X is defined multiple times). The
    fix moves JAR resolution into the task's doFirst using a detached
    configuration
    that forces the download at execution time, after
    dependency resolution is complete.
  • strip-vtm-classes.gradle — hardcoded vtm version. The script no
    longer hardcodes 0.29.0. It auto-detects the version from the core
    library's declared dependencies. Warns if an extension's compileOnly
    vtm version differs from the library's implementation version.
  • strip-vtm-classes.gradle — broken buildFinished JAR restoration.
    The post-build JAR restore handler now reads the lazily-resolved paths
    and is guarded against the task being skipped (no shadowed classes).

v0.8.0

Choose a tag to compare

@jhotadhari jhotadhari released this 07 Aug 22:27

This release is a complete rewrite of the library against the React Native New Architecture
(Fabric + TurboModules). Every component, hook, and native module has been rebuilt from the
ground up. The new design replaces the old bridge-based NativeModules + NativeEventEmitter
pattern with codegen-generated Fabric components and TurboModules, context-driven layer ordering
instead of cloneElement prop injection, and a serialized UI-thread mutation queue that
eliminates the threading races of the old architecture.

Performance is dramatically improved: shared-layer batching collapses hundreds of paths or
markers into a single GPU draw call, marker creation uses batch bridge calls (N markers in
one round-trip), and the new native shared-value bridge delivers map position updates at a true
60 fps with zero JavaScript bridge crossings. The API surface has been streamlined — imperative
map control lives in the useMap() hook, map events arrive as direct Fabric props, and a new
react-native-mapsforge-vtm/reanimated subpackage provides worklet-based overlay positioning.

Added

  • React Native New Architecture — full Fabric + TurboModules support. The library now requires
    React Native 0.76+ with the New Architecture enabled.
  • LayerPathJts — dedicated-layer JTS path component. One native layer per JS component for
    guaranteed render order, with addGreatCircle() for great-circle arcs, built-in
    Douglas-Peucker generalization via Style.generalization, JTS LineString input, and
    per-layer gesture hit-testing (onPress, onLongPress, onDoubleTap).
  • LayerShape — geometric shape overlays. Draw JTS polygons (with holes), circles (center +
    radius in km), rectangles, hexagons, and points with full GeometryStyleJts styling (fill,
    stroke, transparency, stipple) and gesture callbacks.
  • SharedLayer — explicit shared-layer grouping component. Collapses multiple LayerPath or
    Marker children into one native draw call for maximum performance at scale.
  • ReindexScope — sentinel-based render-order placeholders. Ensures async children (lazy-loaded
    markers, data-driven paths) insert at the correct position in the layer stack, preserving the
    invariant that native layer rendering strictly follows React component tree order.
  • useMap() hook — unified imperative map control. Provides animateTo(), getPosition(),
    fitBounds(), triggerEvent() (per-layer), and getDebugLayerDump() for introspection.
    Replaces the old MapContainer ref methods.
  • useMapPosition() from react-native-mapsforge-vtm/reanimated — 60 fps shared-value map
    position tracking. Returns reanimated SharedValues for center, zoom, bearing, and tilt that
    update on every render-thread frame. Worklet consumers read with zero bridge crossings.
  • useMapOverlay() from react-native-mapsforge-vtm/reanimated — worklet-based Mercator
    projection. Converts lat/lng coordinates to screen positions on the UI thread for smooth
    overlay animations. Includes toScreenPosition() and fromScreenPosition() utilities.
  • Native shared-value bridge — bypasses the JavaScript bridge entirely. vtm's render thread
    writes position data directly into C++ Synchronizable primitives via MapPositionWriter;
    a worklet poller reads them each frame and updates standard SharedValue objects. Zero
    bridge crossings at every stage.
  • MapHandleContext + useLayerOrder() — context-driven layer ordering. Each layer component
    registers its position via a stable render-order cursor, debouncing a single native
    reorderLayers call when the resolved order changes. Replaces the old cloneElement /
    static isMapLayer tree walk.
  • useNativeLayerLifecycle() — unified create/remove lifecycle. Tracks a null → false → uuid
    state machine for every layer component, with centralized reportNativeError() and teardown
    race protection via mountedRef.
  • Extension points — MapHandleContext, createLayerOrderRegistry, useLayerOrder,
    useNativeLayerLifecycle, and their types are exported as a stable public API for building
    third-party layer-type libraries (e.g. react-native-mapsforge-vtm-ext-grib).
  • ext-plan skill — interactive scaffolding for extension libraries. Walks through
    architectural decisions (JS-only, TurboModule, or vtm-shadowing patterns) and generates a
    plan file plus scaffolded repo.
  • CanvasAdapterModule — global scale control. Set lineScale, textScale, and symbolScale
    for all mapsforge layers across all MapContainer instances (must be called before the first
    map initializes).
  • Batch marker creation — createMarkers() sends N markers in a single bridge call via
    MarkerBatchQueue, dramatically reducing latency for large marker sets.
  • MapMutationQueue — serialized UI-thread layer mutation queue. All layers().add/remove
    and the batch-level updateMap() flow through a single flush() call on the Main Looper,
    eliminating the threading races of the old ad-hoc approach.
  • ElevationReader / getAltitudeAtPosition() — thin, non-blocking elevation API. Multithreaded
    HGT file loading with interpolation support (3 arc-second DEMs). Replaces the old HgtReader
    with its callback-heavy view props.
  • getDebugLayerDump() — layer introspection. Returns a structured snapshot of every native
    layer's fragment UUIDs, position indices, and type for debugging render-order issues.
  • useLayerDebugInfo() / LayerDebugTree — debug visualization components for inspecting
    the live layer tree in development.
  • Flex layout support — MapContainer now accepts flex: 1 and falls back to measured view
    dimensions when no explicit width/height is set.
  • Bearing and tilt — included in map position data, overlay projection, and map events.
  • RenderThemeMenuLoader — parses <stylemenu> from render-theme XML for
    useRenderStyleOptions().
  • Trailing-edge flush — map position events fire at the render thread's native frame rate
    (~60 fps) with a trailing-edge guarantee (the latest position is always delivered).
  • Comprehensive documentation — rewritten README, new docs/advanced/extending.md,
    docs/advanced/performance.md and inline code comments.
  • FixedWindowRateLimiter — throttles native map-event emission to avoid flooding the
    Fabric event channel.

Changed

  • Breaking: Complete rewrite against React Native New Architecture. The library requires
    React Native 0.76+ with newArchEnabled=true. The old bridge-based architecture is no
    longer supported.
  • Breaking: Layer ordering uses context-based MapHandleContext + useLayerOrder instead
    of cloneElement prop injection. The reactTreeIndex prop is gone — ordering follows
    React component tree position automatically.
  • Breaking: Map events delivered as direct Fabric event props on MapContainer
    (onMapUpdate, onTap, onLongPress, onPause, onResume) instead of a global
    NativeEventEmitter. Each MapContainer receives only its own events.
  • Breaking: useMapEvents() hook removed. Use the onMapUpdate prop on MapContainer
    for callback-based consumption, or useMapPosition() from the reanimated subpackage for
    shared-value consumption.
  • Breaking: useMapLayersCreated() hook removed. Extension authors should use
    useNativeLayerLifecycle() instead.
  • Breaking: usePromiseQueueState(), promiseQueue, usePrevious(), and useRefState()
    removed — these were internal implementation details never intended as public API.
  • Breaking: onMapEvent prop renamed to onMapUpdate.
  • Breaking: mapUpdateInterval prop removed. Events now fire at the render thread's
    native frame rate (~60 fps) with trailing-edge flush.
  • Breaking: responseInclude prop removed. The event shape is now fixed and simplified.
  • Breaking: emitsMapEvents prop removed — map events always emit.
  • Breaking: emitsHardwareKeyUp / onHardwareKeyUp props removed. Hardware key handling
    is no longer built into the map view.
  • Breaking: nativeMapModules export removed. TurboModule specs are internal; the public
    API is the React components, hooks, and types exported from the main entry point.
  • Breaking: HGT/altitude API redesigned. The old HgtReader with its hgtFileInfoPurgeThreshold
    and hgtInterpolation view props is replaced by the thin ElevationReader + imperative
    getAltitudeAtPosition() method on useMap().
  • Breaking: setToBounds() moved to useMap().fitBounds().
  • Breaking: triggerEvent() moved to per-layer dispatch via useMap().
  • Breaking: Zoom level types changed from Int32 to Double/Float throughout the
    native layer, enabling fractional zoom support.
  • Breaking: LayerPath simplificationTolerance prop replaced by external simplify
    library usage (apply simplification to your coordinate arrays before passing them in).
  • LayerPath now uses a shared VectorLayer architecture — many JS LayerPath components
    (or paths inside a SharedLayer) collapse into one native layer, with per-drawable
    priority for ordering. At the JS level the API is identical.
  • LayerMarker / Marker now use a shared ItemizedLayer with sorted insertion by
    position index. The JS API is unchanged.
  • Path rendering uses PathLayer (custom vtm layer subclass) with per-drawable priority
    for correct ordering within the shared layer.
  • Threading model: all layer mutations (add, remove, reorder) are serialized through
    MapMutationQueue.flush() on the UI thread. scheduleUpdate() coalesces per-entry
    updateMap() calls via AtomicBoolean CAS + Handler.post.
  • Example app completely rewritten with 10+ focused examples (basic, mapsforge, hillshading,
    mbtiles-bitmap, scalebar, trigger, many-layers, multi-map, reanimated-overlay,
    layer-order-verification) and a new picker-based navigation UI.
  • Build toolin...
Read more

v0.7.0

Choose a tag to compare

@jhotadhari jhotadhari released this 05 Apr 15:24

This release contains love for elevation data <3

Added

Changed

  • Update dependencies; Update dependency com.github.mapsforge.vtm to version 0.25.0.
  • The java side of the LayerHillshading component is entirely new. Now the component is using the new vtm-hillshading module, implemented in com.github.mapsforge.vtm version 0.25.0. Thank you @devemux86! It's much faster, stable and the generated tiles are more accurate.
  • Change the cache filename for LayerHillshading: Remove dots and dashes. That makes previous caches obsolete.
  • Add props to MapContainer component:
    • hgtInterpolation whether to interpolate elevation or not.
    • hgtFileInfoPurgeThreshold how many neighboring DEMs should be kept in memory.
  • Change HgtReader class (to retrieve altitude at certain coordinates):
    • Better performance. It's multithreaded now and loading new DEM (hgt) files into memory doesn't block the ui thread anymore.
    • Added support for interpolation. The code for interpolation is copied from JOSM Elevation Plugin by Harald Hetzner, thank you @hhtznr!.
    • For now the HgtReader only supports DEMs with a resolution of 3 arc seconds. Instead of fixing this issue, I will wait that this feature will be implemented properly into mapsforge, see #1621
      .

Removed

  • Remove built in themes MOTORIDER_DARK and OSMAGRAY. Because they are not existing anymore in latest version of com.github.mapsforge.vtm.

v0.6.0

Choose a tag to compare

@jhotadhari jhotadhari released this 26 Mar 22:57

Added

  • New props for LayerMapsforge: hasBuildings and hasLabels.
  • New prop for LayerBitmapTile: alpha to control opacity.
  • CanvasAdapterModule to control lineScale, textScale and symbolScale of all mapsforge layers of all MapContainer. The methods have to be called before the first MapContainer is initialized.

Changed

  • Individual cache dirs for LayerHillshading. Added props:
    • cacheDirBase defaults to /. If /, java will fallback to app internal cache dir.
    • cacheDirChild defaults to . If , will fallback to cache dbname.
  • Individual cache dirs for LayerBitmapTile. Added props:
    • cacheDirBase defaults to /. If /, java will fallback to app internal cache dir.
    • cacheDirChild defaults to . If , will fallback to slugify url.

v0.5.3

Choose a tag to compare

@jhotadhari jhotadhari released this 19 Mar 20:50

Added

  • Add prop hgtReadFileRate to MapContainerModule. To control HgtReader read file throttle rate.

Changed

  • HgtReader: Purge hgt file data if not neighbors.

Fixed

  • LayerHillshading: Should update on magnitude or cacheSize changes.
  • LayerBitmapTile: property cacheSize was not working.
  • Missing export useMapLayersCreated.

v0.5.2

Choose a tag to compare

@jhotadhari jhotadhari released this 29 Dec 23:25

Added

  • prop onHardwareKeyUp to MapContainer component. Function that gets called when certain hardware keys are pressed.
  • prop emitsHardwareKeyUp to MapContainer component. Defines which hardware key events are consumed (keycodes: KEYCODE_VOLUME_UP or KEYCODE_VOLUME_DOWN). If they are consumed, these events don't bubble, onHardwareKeyUp js event is triggers and MapContainer:onHardwareKeyUp function is called.

Changed

  • Make all MapEventResponse properties optional.

Fixed

  • HardwareKeyListener consumes all key events and prevents bubbling, breaks all key events. Now it only consumes the event if prop emitsHardwareKeyUp contains event keycode (KEYCODE_VOLUME_UP or KEYCODE_VOLUME_DOWN).
  • Missing type exports: XmlRenderTheme, RenderStyleOptionsCollection.

v0.5.1

Choose a tag to compare

@jhotadhari jhotadhari released this 16 Nov 14:09

Fixed

  • LayerMBTilesBitmap NullPointerException. dataSource.getBounds() might be null.