diff --git a/android/src/main/java/com/rnmapbox/rnmbx/RNMBXPackage.kt b/android/src/main/java/com/rnmapbox/rnmbx/RNMBXPackage.kt index 40fa4ad73..effa67713 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/RNMBXPackage.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/RNMBXPackage.kt @@ -34,6 +34,7 @@ import com.rnmapbox.rnmbx.components.styles.sources.RNMBXImageSourceManager import com.rnmapbox.rnmbx.components.styles.sources.RNMBXRasterDemSourceManager import com.rnmapbox.rnmbx.components.styles.sources.RNMBXRasterSourceManager import com.rnmapbox.rnmbx.components.styles.sources.RNMBXShapeSourceManager +import com.rnmapbox.rnmbx.components.styles.sources.RNMBXShapeSourceModule import com.rnmapbox.rnmbx.components.styles.sources.RNMBXVectorSourceManager import com.rnmapbox.rnmbx.components.styles.terrain.RNMBXTerrainManager import com.rnmapbox.rnmbx.modules.RNMBXLocationModule @@ -67,6 +68,7 @@ class RNMBXPackage : TurboReactPackage() { RNMBXSnapshotModule.REACT_CLASS -> return RNMBXSnapshotModule(reactApplicationContext) RNMBXLogging.REACT_CLASS -> return RNMBXLogging(reactApplicationContext) NativeMapViewModule.NAME -> return NativeMapViewModule(reactApplicationContext, getMapViewTagResolver(reactApplicationContext)) + RNMBXShapeSourceModule.NAME -> return RNMBXShapeSourceModule(reactApplicationContext) } return null } @@ -176,6 +178,15 @@ class RNMBXPackage : TurboReactPackage() { false, // isCxxModule isTurboModule // isTurboModule ) + moduleInfos[RNMBXShapeSourceModule.NAME] = ReactModuleInfo( + RNMBXShapeSourceModule.NAME, + RNMBXShapeSourceModule.NAME, + false, // canOverrideExistingModule + false, // needsEagerInit + false, // hasConstants + false, // isCxxModule + isTurboModule // isTurboModule + ) moduleInfos } } diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapView.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapView.kt index 7237da307..d9647eb0a 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapView.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapView.kt @@ -63,7 +63,7 @@ import com.rnmapbox.rnmbx.components.mapview.helpers.CameraChangeReason import com.rnmapbox.rnmbx.components.mapview.helpers.CameraChangeTracker import com.rnmapbox.rnmbx.components.styles.layers.RNMBXLayer import com.rnmapbox.rnmbx.components.styles.light.RNMBXLight -import com.rnmapbox.rnmbx.components.styles.sources.RCTSource +import com.rnmapbox.rnmbx.components.styles.sources.RNMBXSource import com.rnmapbox.rnmbx.components.styles.terrain.RNMBXTerrain import com.rnmapbox.rnmbx.events.AndroidCallbackEvent import com.rnmapbox.rnmbx.events.IEvent @@ -190,7 +190,7 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie */ public var offscreenAnnotationViewContainer: ViewGroup? = null - private val mSources: MutableMap> + private val mSources: MutableMap> private val mImages: MutableList private var mPointAnnotationManager: PointAnnotationManager? = null private var mActiveMarkerID: AnnotationID = INVALID_ANNOTATION_ID @@ -444,7 +444,7 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie // region Features fun addFeature(childView: View?, childPosition: Int) { var feature: AbstractMapFeature? = null - if (childView is RCTSource<*>) { + if (childView is RNMBXSource<*>) { val source = childView mSources[source.iD.toString()] = source feature = childView as AbstractMapFeature? @@ -491,7 +491,7 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie fun removeFeatureAt(childPosition: Int) { val entry = mFeatures[childPosition] val feature = entry.feature - if (feature is RCTSource<*>) { + if (feature is RNMBXSource<*>) { mSources.remove(feature.iD) } else if (feature is RNMBXPointAnnotation) { val annotation = feature @@ -553,9 +553,9 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie } - private val allTouchableSources: List> + private val allTouchableSources: List> private get() { - val sources: MutableList> = ArrayList() + val sources: MutableList> = ArrayList() for (key in mSources.keys) { val source = mSources[key] if (source != null && source.hasPressListener()) { @@ -565,14 +565,14 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie return sources } - private fun getTouchableSourceWithHighestZIndex(sources: List>?): RCTSource<*>? { + private fun getTouchableSourceWithHighestZIndex(sources: List>?): RNMBXSource<*>? { if (sources == null || sources.size == 0) { return null } if (sources.size == 1) { return sources[0] } - val layerToSourceMap: MutableMap> = HashMap() + val layerToSourceMap: MutableMap> = HashMap() for (source in sources) { val layerIDs: Array? = source.layerIDs.toTypedArray() if (layerIDs != null) { @@ -662,13 +662,13 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie } interface HandleTap { - fun run(hitTouchableSources: List?>?, hits: Map?>) + fun run(hitTouchableSources: List?>?, hits: Map?>) } fun handleTapInSources( - sources: LinkedList>, screenPoint: ScreenCoordinate, + sources: LinkedList>, screenPoint: ScreenCoordinate, hits: HashMap?>, - hitTouchableSources: ArrayList?>, + hitTouchableSources: ArrayList?>, handleTap: HandleTap ) { if (sources.isEmpty()) { @@ -723,11 +723,11 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie val hits = HashMap?>() if (screenPoint != null) { handleTapInSources(LinkedList(touchableSources), screenPoint, hits, ArrayList(), object : HandleTap { - override fun run(hitTouchableSources: List?>?, hits: Map?>) { + override fun run(hitTouchableSources: List?>?, hits: Map?>) { if (hits.size > 0) { - val source = getTouchableSourceWithHighestZIndex(hitTouchableSources as List>?) + val source = getTouchableSourceWithHighestZIndex(hitTouchableSources as List>?) if (source != null && source.hasPressListener() && source.iD != null && source.iD in hits) { - source.onPress(RCTSource.OnPressEvent( + source.onPress(RNMBXSource.OnPressEvent( hits[source.iD] as List, GeoJSONUtils.toLatLng(point), PointF(screenPoint.x.toFloat(), screenPoint.y.toFloat()) diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXImageSource.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXImageSource.kt index 683b8a0cb..be2207289 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXImageSource.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXImageSource.kt @@ -8,7 +8,7 @@ import com.mapbox.maps.extension.style.sources.generated.ImageSource import com.rnmapbox.rnmbx.utils.LatLngQuad import java.net.URL -class RNMBXImageSource(context: Context?) : RCTSource(context) { +class RNMBXImageSource(context: Context?) : RNMBXSource(context) { private var mURL: URL? = null private var mResourceId = 0 private var mCoordQuad: LatLngQuad? = null diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSource.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSource.kt index 7c918c8d7..d5d82313e 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSource.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSource.kt @@ -4,6 +4,7 @@ import android.content.Context import com.mapbox.maps.extension.style.sources.generated.GeoJsonSource import com.rnmapbox.rnmbx.utils.ImageEntry import android.graphics.drawable.BitmapDrawable +import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReadableMap import com.rnmapbox.rnmbx.components.mapview.RNMBXMapView import com.rnmapbox.rnmbx.events.FeatureClickEvent @@ -23,7 +24,7 @@ import java.util.HashMap import com.rnmapbox.rnmbx.v11compat.feature.* class RNMBXShapeSource(context: Context, private val mManager: RNMBXShapeSourceManager) : - RCTSource(context) { + RNMBXSource(context) { private var mURL: URL? = null private var mShape: String? = null private var mCluster: Boolean? = null @@ -176,18 +177,14 @@ class RNMBXShapeSource(context: Context, private val mManager: RNMBXShapeSourceM } } - private fun callbackSuccess(callbackID: String, payload: WritableMap) { - val event = AndroidCallbackEvent(this, callbackID, payload) - mManager.handleEvent(event) + private fun callbackSuccess(payload: WritableMap, promise: Promise) { + promise.resolve(payload) } - private fun callbackError(callbackID: String, error: String, where: String) { - val payload: WritableMap = WritableNativeMap() - payload.putString("error", "$where: $error") - val event = AndroidCallbackEvent(this, callbackID, payload) - mManager.handleEvent(event) + private fun callbackError(error: String, where: String, promise: Promise) { + promise.reject("error", "$where: $error") } - fun getClusterExpansionZoom(callbackID: String, featureJSON: String) { + fun getClusterExpansionZoom(featureJSON: String, promise: Promise) { val feature = Feature.fromJson(featureJSON) mMap!!.getGeoJsonClusterExpansionZoom(iD!!, feature, QueryFeatureExtensionCallback { features -> @@ -198,28 +195,29 @@ class RNMBXShapeSource(context: Context, private val mManager: RNMBXShapeSourceM if (contents is Long) { val payload: WritableMap = WritableNativeMap() payload.putInt("data", contents.toInt()) - callbackSuccess(callbackID, payload) + callbackSuccess(payload, promise) return@QueryFeatureExtensionCallback } else { callbackError( - callbackID, + "Not a number: $contents", - "getClusterExpansionZoom/getGeoJsonClusterExpansionZoom" + "getClusterExpansionZoom/getGeoJsonClusterExpansionZoom", + promise ) return@QueryFeatureExtensionCallback } } else { callbackError( - callbackID, features.error ?: "Unknown error", - "getClusterExpansionZoom/getGeoJsonClusterExpansionZoom" + "getClusterExpansionZoom/getGeoJsonClusterExpansionZoom", + promise ) return@QueryFeatureExtensionCallback } }) } - fun getClusterLeaves(callbackID: String, featureJSON: String, number: Int, offset: Int) { + fun getClusterLeaves(featureJSON: String, number: Int, offset: Int, promise: Promise) { val feature = Feature.fromJson(featureJSON) val _this = this @@ -232,19 +230,19 @@ class RNMBXShapeSource(context: Context, private val mManager: RNMBXShapeSourceM "data", FeatureCollection.fromFeatures(leaves!!).toJson() ) - callbackSuccess(callbackID, payload) + callbackSuccess(payload, promise) } else { callbackError( - callbackID, features.error ?: "Unknown error", - "getClusterLeaves/getGeoJsonClusterLeaves" + "getClusterLeaves/getGeoJsonClusterLeaves", + promise ) return@QueryFeatureExtensionCallback } }) } - fun getClusterChildren(callbackID: String, featureJSON: String) { + fun getClusterChildren(featureJSON: String, promise: Promise) { val feature = Feature.fromJson(featureJSON) val _this = this @@ -257,12 +255,12 @@ class RNMBXShapeSource(context: Context, private val mManager: RNMBXShapeSourceM "data", FeatureCollection.fromFeatures(children!!).toJson() ) - callbackSuccess(callbackID, payload) + callbackSuccess(payload, promise) }else { callbackError( - callbackID, features.error ?: "Unknown error", - "getClusterLeaves/queryFeatureExtensions" + "getClusterLeaves/queryFeatureExtensions", + promise ) return@QueryFeatureExtensionCallback } diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSourceManager.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSourceManager.kt index 404fdef1a..25ff43f91 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSourceManager.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSourceManager.kt @@ -1,13 +1,11 @@ package com.rnmapbox.rnmbx.components.styles.sources -import android.util.Log import android.view.View import com.facebook.react.bridge.ReactApplicationContext import com.rnmapbox.rnmbx.components.AbstractEventEmitter import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.annotations.ReactProp import com.facebook.react.bridge.ReadableMap -import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableType import com.facebook.react.common.MapBuilder import com.mapbox.bindgen.Value @@ -153,52 +151,8 @@ class RNMBXShapeSourceManager(private val mContext: ReactApplicationContext) : .build() } - override fun getCommandsMap(): Map? { - return MapBuilder.builder() - .put("features", METHOD_FEATURES) - .put("getClusterExpansionZoom", METHOD_GET_CLUSTER_EXPANSION_ZOOM) - .put("getClusterLeaves", METHOD_GET_CLUSTER_LEAVES) - .put("getClusterChildren", METHOD_GET_CLUSTER_CHILDREN) - .build() - } - - override fun receiveCommand(source: RNMBXShapeSource, commandID: Int, args: ReadableArray?) { - if (args == null) { - return - } - - val callbackID = args.getString(0); - - when (commandID) { - METHOD_FEATURES -> source.querySourceFeatures( - callbackID, - ExpressionParser.from(args.getArray(1)) - ) - METHOD_GET_CLUSTER_EXPANSION_ZOOM -> source.getClusterExpansionZoom( - callbackID, - args.getString(1) - ) - METHOD_GET_CLUSTER_LEAVES -> source.getClusterLeaves( - callbackID, - args.getString(1), - args.getInt(2), - args.getInt(3) - ) - METHOD_GET_CLUSTER_CHILDREN -> source.getClusterChildren( - callbackID, - args.getString(1) - ) - } - } - companion object { const val LOG_TAG = "RNMBXShapeSourceMgr" const val REACT_CLASS = "RNMBXShapeSource" - - //region React Methods - const val METHOD_FEATURES = 103 - const val METHOD_GET_CLUSTER_EXPANSION_ZOOM = 104 - const val METHOD_GET_CLUSTER_LEAVES = 105 - const val METHOD_GET_CLUSTER_CHILDREN = 106 } } diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSourceModule.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSourceModule.kt new file mode 100644 index 000000000..a7ac1f214 --- /dev/null +++ b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSourceModule.kt @@ -0,0 +1,72 @@ +package com.rnmapbox.rnmbx.components.styles.sources + +import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactMethod +import com.facebook.react.module.annotations.ReactModule +import com.facebook.react.uimanager.UIManagerHelper +import com.facebook.react.uimanager.common.UIManagerType +import com.rnmapbox.rnmbx.BuildConfig +import com.rnmapbox.rnmbx.NativeRNMBXShapeSourceModuleSpec + +@ReactModule(name = RNMBXShapeSourceModule.NAME) +class RNMBXShapeSourceModule(reactContext: ReactApplicationContext?) : + NativeRNMBXShapeSourceModuleSpec(reactContext) { + + private fun withShapeSourceOnUIThread(viewRef: Double?, promise: Promise, fn: (RNMBXShapeSource) -> Unit) { + if (viewRef == null) { + promise.reject(Exception("viewRef is null for RNMBXShapeSource")) + } else { + + reactApplicationContext.runOnUiQueueThread { + val manager = if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) + UIManagerHelper.getUIManager(reactApplicationContext, UIManagerType.FABRIC) + else + UIManagerHelper.getUIManager(reactApplicationContext, UIManagerType.DEFAULT) + + val view = manager?.resolveView(viewRef.toInt()) as? RNMBXShapeSource + + if (view != null) { + fn(view) + } else { + promise.reject(Exception("cannot find map view for tag ${viewRef.toInt()}")) + } + } + } + } + + companion object { + const val NAME = "RNMBXShapeSourceModule" + } + + @ReactMethod + override fun getClusterExpansionZoom( + viewRef: Double?, + featureJSON: String, + promise: Promise + ) { + withShapeSourceOnUIThread(viewRef, promise) { + it.getClusterExpansionZoom(featureJSON, promise) + } + } + + @ReactMethod + override fun getClusterLeaves( + viewRef: Double?, + featureJSON: String, + number: Double, + offset: Double, + promise: Promise + ) { + withShapeSourceOnUIThread(viewRef, promise) { + it.getClusterLeaves(featureJSON, number.toInt(), offset.toInt(), promise) + } + } + + @ReactMethod + override fun getClusterChildren(viewRef: Double?, featureJSON: String, promise: Promise) { + withShapeSourceOnUIThread(viewRef, promise) { + it.getClusterChildren(featureJSON, promise) + } + } +} \ No newline at end of file diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RCTSource.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXSource.kt similarity index 92% rename from android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RCTSource.kt rename to android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXSource.kt index b663926f8..0652a18e1 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RCTSource.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXSource.kt @@ -8,7 +8,7 @@ import com.rnmapbox.rnmbx.components.mapview.RNMBXMapView import com.mapbox.maps.MapboxMap import com.rnmapbox.rnmbx.components.styles.sources.AbstractSourceConsumer import com.facebook.react.bridge.ReadableMap -import com.rnmapbox.rnmbx.components.styles.sources.RCTSource +import com.rnmapbox.rnmbx.components.styles.sources.RNMBXSource import android.graphics.PointF import android.view.View import com.facebook.react.common.MapBuilder @@ -17,7 +17,7 @@ import com.mapbox.maps.Style import com.mapbox.maps.extension.style.StyleContract import com.mapbox.maps.extension.style.sources.Source import com.rnmapbox.rnmbx.components.RemovalReason -import com.rnmapbox.rnmbx.components.styles.sources.RCTSource.OnPressEvent +import com.rnmapbox.rnmbx.components.styles.sources.RNMBXSource.OnPressEvent import com.rnmapbox.rnmbx.utils.LatLng import com.rnmapbox.rnmbx.utils.Logger import java.lang.ClassCastException @@ -27,9 +27,9 @@ import java.util.HashMap data class FeatureInfo(val feature: AbstractMapFeature?, var added: Boolean) { } -abstract class RCTSource(context: Context?) : AbstractMapFeature(context) { +abstract class RNMBXSource(context: Context?) : AbstractMapFeature(context) { @JvmField - protected var mMap: MapboxMap? = null + var mMap: MapboxMap? = null var iD: String? = null @JvmField protected var mSource: T? = null @@ -61,7 +61,7 @@ abstract class RCTSource(context: Context?) : AbstractMapFeature(co if (hasNoDataSoRefersToExisting()) { Logger.w( LOG_TAG, - "RCTSource: soure with id: $id seems to refer to existing value but existing flag is not set. This is deprecated." + "RNMBXSource: soure with id: $id seems to refer to existing value but existing flag is not set. This is deprecated." ) result = true } else { @@ -141,7 +141,7 @@ abstract class RCTSource(context: Context?) : AbstractMapFeature(co mMap = mapView.getMapboxMap() val map = mMap if (map == null) { - Logger.e("RCTSource", "map is exepted to be valid but was null, $iD") + Logger.e("RNMBXSource", "map is exepted to be valid but was null, $iD") return } val style = map.getStyle() @@ -171,7 +171,7 @@ abstract class RCTSource(context: Context?) : AbstractMapFeature(co try { iD?.let { mMap?.getStyle()?.removeStyleSource(it) } } catch (ex: Throwable) { - Logger.w(LOG_TAG, String.format("RCTSource.removeFromMap: %s - %s", mSource, ex.message), ex) + Logger.w(LOG_TAG, String.format("RNMBXSource.removeFromMap: %s - %s", mSource, ex.message), ex) } } return super.removeFromMap(mapView, reason) @@ -227,7 +227,7 @@ abstract class RCTSource(context: Context?) : AbstractMapFeature(co companion object { const val DEFAULT_ID = "composite" - const val LOG_TAG = "RCTSource" + const val LOG_TAG = "RNMBXSource" const val DEFAULT_HITBOX_WIDTH = 44.0 const val DEFAULT_HITBOX_HEIGHT = 44.0 @JvmStatic diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXTileSource.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXTileSource.kt index f47dab02f..91541bc09 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXTileSource.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXTileSource.kt @@ -7,7 +7,7 @@ import com.mapbox.maps.extension.style.sources.TileSet import com.mapbox.maps.extension.style.sources.generated.Scheme import java.util.* -abstract class RNMBXTileSource(context: Context?) : RCTSource(context) { +abstract class RNMBXTileSource(context: Context?) : RNMBXSource(context) { var uRL: String? = null public var tileUrlTemplates: Collection = ArrayList() var attribution: String? = null diff --git a/android/src/main/java/com/rnmapbox/rnmbx/events/FeatureClickEvent.java b/android/src/main/java/com/rnmapbox/rnmbx/events/FeatureClickEvent.java index 08a7f9622..b396e492b 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/events/FeatureClickEvent.java +++ b/android/src/main/java/com/rnmapbox/rnmbx/events/FeatureClickEvent.java @@ -7,7 +7,7 @@ import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.mapbox.geojson.Feature; -import com.rnmapbox.rnmbx.components.styles.sources.RCTSource; +import com.rnmapbox.rnmbx.components.styles.sources.RNMBXSource; import com.rnmapbox.rnmbx.events.constants.EventKeys; import com.rnmapbox.rnmbx.events.constants.EventTypes; import com.rnmapbox.rnmbx.utils.ConvertUtils; @@ -62,17 +62,17 @@ public WritableMap getPayload() { return map; } - public static FeatureClickEvent makeShapeSourceEvent(View view, RCTSource.OnPressEvent event) { + public static FeatureClickEvent makeShapeSourceEvent(View view, RNMBXSource.OnPressEvent event) { return new FeatureClickEvent(view, EventKeys.SHAPE_SOURCE_LAYER_CLICK, EventTypes.SHAPE_SOURCE_LAYER_CLICK, event.getFeatures(), event.getLatLng(), event.getScreenPoint()); } - public static FeatureClickEvent makeVectorSourceEvent(View view, RCTSource.OnPressEvent event) { + public static FeatureClickEvent makeVectorSourceEvent(View view, RNMBXSource.OnPressEvent event) { return new FeatureClickEvent(view, EventKeys.VECTOR_SOURCE_LAYER_CLICK, EventTypes.VECTOR_SOURCE_LAYER_CLICK, event.getFeatures(), event.getLatLng(), event.getScreenPoint()); } - public static FeatureClickEvent makeRasterSourceEvent(View view, RCTSource.OnPressEvent event) { + public static FeatureClickEvent makeRasterSourceEvent(View view, RNMBXSource.OnPressEvent event) { return new FeatureClickEvent(view, EventKeys.RASTER_SOURCE_LAYER_CLICK, EventTypes.RASTER_SOURCE_LAYER_CLICK, event.getFeatures(), event.getLatLng(), event.getScreenPoint()); } diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXImageSourceManagerDelegate.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXImageSourceManagerDelegate.java new file mode 100644 index 000000000..d0f69992f --- /dev/null +++ b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXImageSourceManagerDelegate.java @@ -0,0 +1,41 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaDelegate.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.DynamicFromObject; +import com.facebook.react.uimanager.BaseViewManagerDelegate; +import com.facebook.react.uimanager.BaseViewManagerInterface; + +public class RNMBXImageSourceManagerDelegate & RNMBXImageSourceManagerInterface> extends BaseViewManagerDelegate { + public RNMBXImageSourceManagerDelegate(U viewManager) { + super(viewManager); + } + @Override + public void setProperty(T view, String propName, @Nullable Object value) { + switch (propName) { + case "id": + mViewManager.setId(view, new DynamicFromObject(value)); + break; + case "existing": + mViewManager.setExisting(view, new DynamicFromObject(value)); + break; + case "url": + mViewManager.setUrl(view, new DynamicFromObject(value)); + break; + case "coordinates": + mViewManager.setCoordinates(view, new DynamicFromObject(value)); + break; + default: + super.setProperty(view, propName, value); + } + } +} diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXImageSourceManagerInterface.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXImageSourceManagerInterface.java new file mode 100644 index 000000000..18e5bf4dd --- /dev/null +++ b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXImageSourceManagerInterface.java @@ -0,0 +1,20 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaInterface.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import com.facebook.react.bridge.Dynamic; + +public interface RNMBXImageSourceManagerInterface { + void setId(T view, Dynamic value); + void setExisting(T view, Dynamic value); + void setUrl(T view, Dynamic value); + void setCoordinates(T view, Dynamic value); +} diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterDemSourceManagerDelegate.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterDemSourceManagerDelegate.java new file mode 100644 index 000000000..6a0ef3baf --- /dev/null +++ b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterDemSourceManagerDelegate.java @@ -0,0 +1,50 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaDelegate.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.DynamicFromObject; +import com.facebook.react.uimanager.BaseViewManagerDelegate; +import com.facebook.react.uimanager.BaseViewManagerInterface; + +public class RNMBXRasterDemSourceManagerDelegate & RNMBXRasterDemSourceManagerInterface> extends BaseViewManagerDelegate { + public RNMBXRasterDemSourceManagerDelegate(U viewManager) { + super(viewManager); + } + @Override + public void setProperty(T view, String propName, @Nullable Object value) { + switch (propName) { + case "id": + mViewManager.setId(view, new DynamicFromObject(value)); + break; + case "existing": + mViewManager.setExisting(view, new DynamicFromObject(value)); + break; + case "url": + mViewManager.setUrl(view, new DynamicFromObject(value)); + break; + case "tileUrlTemplates": + mViewManager.setTileUrlTemplates(view, new DynamicFromObject(value)); + break; + case "minZoomLevel": + mViewManager.setMinZoomLevel(view, new DynamicFromObject(value)); + break; + case "maxZoomLevel": + mViewManager.setMaxZoomLevel(view, new DynamicFromObject(value)); + break; + case "tileSize": + mViewManager.setTileSize(view, new DynamicFromObject(value)); + break; + default: + super.setProperty(view, propName, value); + } + } +} diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterDemSourceManagerInterface.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterDemSourceManagerInterface.java new file mode 100644 index 000000000..e1da4ca30 --- /dev/null +++ b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterDemSourceManagerInterface.java @@ -0,0 +1,23 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaInterface.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import com.facebook.react.bridge.Dynamic; + +public interface RNMBXRasterDemSourceManagerInterface { + void setId(T view, Dynamic value); + void setExisting(T view, Dynamic value); + void setUrl(T view, Dynamic value); + void setTileUrlTemplates(T view, Dynamic value); + void setMinZoomLevel(T view, Dynamic value); + void setMaxZoomLevel(T view, Dynamic value); + void setTileSize(T view, Dynamic value); +} diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterSourceManagerDelegate.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterSourceManagerDelegate.java new file mode 100644 index 000000000..3e6fafe73 --- /dev/null +++ b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterSourceManagerDelegate.java @@ -0,0 +1,56 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaDelegate.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.DynamicFromObject; +import com.facebook.react.uimanager.BaseViewManagerDelegate; +import com.facebook.react.uimanager.BaseViewManagerInterface; + +public class RNMBXRasterSourceManagerDelegate & RNMBXRasterSourceManagerInterface> extends BaseViewManagerDelegate { + public RNMBXRasterSourceManagerDelegate(U viewManager) { + super(viewManager); + } + @Override + public void setProperty(T view, String propName, @Nullable Object value) { + switch (propName) { + case "id": + mViewManager.setId(view, new DynamicFromObject(value)); + break; + case "existing": + mViewManager.setExisting(view, new DynamicFromObject(value)); + break; + case "url": + mViewManager.setUrl(view, new DynamicFromObject(value)); + break; + case "tileUrlTemplates": + mViewManager.setTileUrlTemplates(view, new DynamicFromObject(value)); + break; + case "minZoomLevel": + mViewManager.setMinZoomLevel(view, new DynamicFromObject(value)); + break; + case "maxZoomLevel": + mViewManager.setMaxZoomLevel(view, new DynamicFromObject(value)); + break; + case "tileSize": + mViewManager.setTileSize(view, new DynamicFromObject(value)); + break; + case "tms": + mViewManager.setTms(view, new DynamicFromObject(value)); + break; + case "attribution": + mViewManager.setAttribution(view, new DynamicFromObject(value)); + break; + default: + super.setProperty(view, propName, value); + } + } +} diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterSourceManagerInterface.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterSourceManagerInterface.java new file mode 100644 index 000000000..3361af80c --- /dev/null +++ b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterSourceManagerInterface.java @@ -0,0 +1,25 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaInterface.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import com.facebook.react.bridge.Dynamic; + +public interface RNMBXRasterSourceManagerInterface { + void setId(T view, Dynamic value); + void setExisting(T view, Dynamic value); + void setUrl(T view, Dynamic value); + void setTileUrlTemplates(T view, Dynamic value); + void setMinZoomLevel(T view, Dynamic value); + void setMaxZoomLevel(T view, Dynamic value); + void setTileSize(T view, Dynamic value); + void setTms(T view, Dynamic value); + void setAttribution(T view, Dynamic value); +} diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXShapeSourceManagerDelegate.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXShapeSourceManagerDelegate.java new file mode 100644 index 000000000..bc61b9324 --- /dev/null +++ b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXShapeSourceManagerDelegate.java @@ -0,0 +1,77 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaDelegate.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.DynamicFromObject; +import com.facebook.react.uimanager.BaseViewManagerDelegate; +import com.facebook.react.uimanager.BaseViewManagerInterface; + +public class RNMBXShapeSourceManagerDelegate & RNMBXShapeSourceManagerInterface> extends BaseViewManagerDelegate { + public RNMBXShapeSourceManagerDelegate(U viewManager) { + super(viewManager); + } + @Override + public void setProperty(T view, String propName, @Nullable Object value) { + switch (propName) { + case "id": + mViewManager.setId(view, new DynamicFromObject(value)); + break; + case "existing": + mViewManager.setExisting(view, new DynamicFromObject(value)); + break; + case "url": + mViewManager.setUrl(view, new DynamicFromObject(value)); + break; + case "shape": + mViewManager.setShape(view, new DynamicFromObject(value)); + break; + case "cluster": + mViewManager.setCluster(view, new DynamicFromObject(value)); + break; + case "clusterRadius": + mViewManager.setClusterRadius(view, new DynamicFromObject(value)); + break; + case "clusterMaxZoomLevel": + mViewManager.setClusterMaxZoomLevel(view, new DynamicFromObject(value)); + break; + case "clusterProperties": + mViewManager.setClusterProperties(view, new DynamicFromObject(value)); + break; + case "maxZoomLevel": + mViewManager.setMaxZoomLevel(view, new DynamicFromObject(value)); + break; + case "buffer": + mViewManager.setBuffer(view, new DynamicFromObject(value)); + break; + case "tolerance": + mViewManager.setTolerance(view, new DynamicFromObject(value)); + break; + case "lineMetrics": + mViewManager.setLineMetrics(view, new DynamicFromObject(value)); + break; + case "images": + mViewManager.setImages(view, new DynamicFromObject(value)); + break; + case "nativeImages": + mViewManager.setNativeImages(view, new DynamicFromObject(value)); + break; + case "hasPressListener": + mViewManager.setHasPressListener(view, new DynamicFromObject(value)); + break; + case "hitbox": + mViewManager.setHitbox(view, new DynamicFromObject(value)); + break; + default: + super.setProperty(view, propName, value); + } + } +} diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXShapeSourceManagerInterface.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXShapeSourceManagerInterface.java new file mode 100644 index 000000000..c4aca5af4 --- /dev/null +++ b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXShapeSourceManagerInterface.java @@ -0,0 +1,32 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaInterface.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import com.facebook.react.bridge.Dynamic; + +public interface RNMBXShapeSourceManagerInterface { + void setId(T view, Dynamic value); + void setExisting(T view, Dynamic value); + void setUrl(T view, Dynamic value); + void setShape(T view, Dynamic value); + void setCluster(T view, Dynamic value); + void setClusterRadius(T view, Dynamic value); + void setClusterMaxZoomLevel(T view, Dynamic value); + void setClusterProperties(T view, Dynamic value); + void setMaxZoomLevel(T view, Dynamic value); + void setBuffer(T view, Dynamic value); + void setTolerance(T view, Dynamic value); + void setLineMetrics(T view, Dynamic value); + void setImages(T view, Dynamic value); + void setNativeImages(T view, Dynamic value); + void setHasPressListener(T view, Dynamic value); + void setHitbox(T view, Dynamic value); +} diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXVectorSourceManagerDelegate.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXVectorSourceManagerDelegate.java new file mode 100644 index 000000000..c47abe3d6 --- /dev/null +++ b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXVectorSourceManagerDelegate.java @@ -0,0 +1,59 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaDelegate.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.DynamicFromObject; +import com.facebook.react.uimanager.BaseViewManagerDelegate; +import com.facebook.react.uimanager.BaseViewManagerInterface; + +public class RNMBXVectorSourceManagerDelegate & RNMBXVectorSourceManagerInterface> extends BaseViewManagerDelegate { + public RNMBXVectorSourceManagerDelegate(U viewManager) { + super(viewManager); + } + @Override + public void setProperty(T view, String propName, @Nullable Object value) { + switch (propName) { + case "id": + mViewManager.setId(view, new DynamicFromObject(value)); + break; + case "existing": + mViewManager.setExisting(view, new DynamicFromObject(value)); + break; + case "url": + mViewManager.setUrl(view, new DynamicFromObject(value)); + break; + case "tileUrlTemplates": + mViewManager.setTileUrlTemplates(view, new DynamicFromObject(value)); + break; + case "attribution": + mViewManager.setAttribution(view, new DynamicFromObject(value)); + break; + case "maxZoomLevel": + mViewManager.setMaxZoomLevel(view, new DynamicFromObject(value)); + break; + case "minZoomLevel": + mViewManager.setMinZoomLevel(view, new DynamicFromObject(value)); + break; + case "tms": + mViewManager.setTms(view, new DynamicFromObject(value)); + break; + case "hasPressListener": + mViewManager.setHasPressListener(view, new DynamicFromObject(value)); + break; + case "hitbox": + mViewManager.setHitbox(view, new DynamicFromObject(value)); + break; + default: + super.setProperty(view, propName, value); + } + } +} diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXVectorSourceManagerInterface.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXVectorSourceManagerInterface.java new file mode 100644 index 000000000..65d0233e8 --- /dev/null +++ b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXVectorSourceManagerInterface.java @@ -0,0 +1,26 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaInterface.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import com.facebook.react.bridge.Dynamic; + +public interface RNMBXVectorSourceManagerInterface { + void setId(T view, Dynamic value); + void setExisting(T view, Dynamic value); + void setUrl(T view, Dynamic value); + void setTileUrlTemplates(T view, Dynamic value); + void setAttribution(T view, Dynamic value); + void setMaxZoomLevel(T view, Dynamic value); + void setMinZoomLevel(T view, Dynamic value); + void setTms(T view, Dynamic value); + void setHasPressListener(T view, Dynamic value); + void setHitbox(T view, Dynamic value); +} diff --git a/android/src/main/old-arch/com/rnmapbox/rnmbx/NativeRNMBXShapeSourceModuleSpec.java b/android/src/main/old-arch/com/rnmapbox/rnmbx/NativeRNMBXShapeSourceModuleSpec.java new file mode 100644 index 000000000..f0b8de373 --- /dev/null +++ b/android/src/main/old-arch/com/rnmapbox/rnmbx/NativeRNMBXShapeSourceModuleSpec.java @@ -0,0 +1,48 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleJavaSpec.js + * + * @nolint + */ + +package com.rnmapbox.rnmbx; + +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReactModuleWithSpec; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class NativeRNMBXShapeSourceModuleSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { + public static final String NAME = "RNMBXShapeSourceModule"; + + public NativeRNMBXShapeSourceModuleSpec(ReactApplicationContext reactContext) { + super(reactContext); + } + + @Override + public @Nonnull String getName() { + return NAME; + } + + @ReactMethod + @DoNotStrip + public abstract void getClusterExpansionZoom(@Nullable Double viewRef, String featureJSON, Promise promise); + + @ReactMethod + @DoNotStrip + public abstract void getClusterLeaves(@Nullable Double viewRef, String featureJSON, double number, double offset, Promise promise); + + @ReactMethod + @DoNotStrip + public abstract void getClusterChildren(@Nullable Double viewRef, String featureJSON, Promise promise); +} diff --git a/docs/ShapeSource.md b/docs/ShapeSource.md index 179e84f6e..f9314dcce 100644 --- a/docs/ShapeSource.md +++ b/docs/ShapeSource.md @@ -192,22 +192,6 @@ FIX ME NO DESCRIPTION ## methods -### features([filter]) - -Returns all features from the source that match the query parameters whether the feature is currently
rendered on the map. - -#### arguments -| Name | Type | Required | Description | -| ---- | :--: | :------: | :----------: | -| `filter` | `Array` | `No` | an optional filter statement to filter the returned Features. | - - - -```javascript -shapeSource.features() -``` - - ### getClusterExpansionZoom(feature) Returns the zoom needed to expand the cluster. diff --git a/docs/VectorSource.md b/docs/VectorSource.md index 34f5c24d7..bee3e4005 100644 --- a/docs/VectorSource.md +++ b/docs/VectorSource.md @@ -136,23 +136,6 @@ FIX ME NO DESCRIPTION ## methods -### features([layerIDs][, filter]) - -Returns all features that match the query parameters regardless of whether or not the feature is
currently rendered on the map. The domain of the query includes all currently-loaded vector tiles
and GeoJSON source tiles. This function does not check tiles outside of the visible viewport. - -#### arguments -| Name | Type | Required | Description | -| ---- | :--: | :------: | :----------: | -| `layerIDs` | `Array` | `No` | A set of strings that correspond to the names of layers defined in the current style. Only the features contained in these layers are included in the returned array. | -| `filter` | `Array` | `No` | an optional filter statement to filter the returned Features. | - - - -```javascript -vectorSource.features(['id1', 'id2']) -``` - - ### onPress(event) diff --git a/docs/docs.json b/docs/docs.json index a45abe391..f0961a366 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -4737,32 +4737,6 @@ "description": "ShapeSource is a map content source that supplies vector shapes to be shown on the map.\nThe shape may be an url or a GeoJSON object", "displayName": "ShapeSource", "methods": [ - { - "name": "features", - "docblock": "Returns all features from the source that match the query parameters whether the feature is currently\nrendered on the map.\n\n@example\nshapeSource.features()\n\n@param {Array=} filter - an optional filter statement to filter the returned Features.\n@return {FeatureCollection}", - "modifiers": [ - "async" - ], - "params": [ - { - "name": "filter", - "description": "an optional filter statement to filter the returned Features.", - "type": { - "name": "Array" - }, - "optional": true - } - ], - "returns": { - "type": { - "name": "FeatureCollection" - } - }, - "description": "Returns all features from the source that match the query parameters whether the feature is currently\nrendered on the map.", - "examples": [ - "\nshapeSource.features()\n\n" - ] - }, { "name": "getClusterExpansionZoom", "docblock": "Returns the zoom needed to expand the cluster.\n\n@example\nconst zoom = await shapeSource.getClusterExpansionZoom(clusterId);\n\n@param {Feature} feature - The feature cluster to expand.\n@return {number}", @@ -7311,40 +7285,6 @@ "description": "VectorSource is a map content source that supplies tiled vector data in Mapbox Vector Tile format to be shown on the map.\nThe location of and metadata about the tiles are defined either by an option dictionary or by an external file that conforms to the TileJSON specification.", "displayName": "VectorSource", "methods": [ - { - "name": "features", - "docblock": "Returns all features that match the query parameters regardless of whether or not the feature is\ncurrently rendered on the map. The domain of the query includes all currently-loaded vector tiles\nand GeoJSON source tiles. This function does not check tiles outside of the visible viewport.\n\n@example\nvectorSource.features(['id1', 'id2'])\n\n@param {Array=} layerIDs - A set of strings that correspond to the names of layers defined in the current style. Only the features contained in these layers are included in the returned array.\n@param {Array=} filter - an optional filter statement to filter the returned Features.\n@return {FeatureCollection}", - "modifiers": [ - "async" - ], - "params": [ - { - "name": "layerIDs", - "description": "A set of strings that correspond to the names of layers defined in the current style. Only the features contained in these layers are included in the returned array.", - "type": { - "name": "Array" - }, - "optional": true - }, - { - "name": "filter", - "description": "an optional filter statement to filter the returned Features.", - "type": { - "name": "Array" - }, - "optional": true - } - ], - "returns": { - "type": { - "name": "FeatureCollection" - } - }, - "description": "Returns all features that match the query parameters regardless of whether or not the feature is\ncurrently rendered on the map. The domain of the query includes all currently-loaded vector tiles\nand GeoJSON source tiles. This function does not check tiles outside of the visible viewport.", - "examples": [ - "\nvectorSource.features(['id1', 'id2'])\n\n" - ] - }, { "name": "onPress", "docblock": null, diff --git a/example/src/examples/FillRasterLayer/CustomVectorSource.js b/example/src/examples/FillRasterLayer/CustomVectorSource.js index d536161f3..8ee82058e 100755 --- a/example/src/examples/FillRasterLayer/CustomVectorSource.js +++ b/example/src/examples/FillRasterLayer/CustomVectorSource.js @@ -1,11 +1,9 @@ import React from 'react'; import MapboxGL from '@rnmapbox/maps'; -import { Text } from 'react-native'; import sheet from '../../styles/sheet'; import BaseExamplePropTypes from '../common/BaseExamplePropTypes'; import Page from '../common/Page'; -import Bubble from '../common/Bubble'; const styles = { boxFill: { @@ -43,7 +41,6 @@ class CustomVectorSource extends React.PureComponent { }; render() { - const { featuresCount } = this.state; return ( @@ -69,10 +66,6 @@ class CustomVectorSource extends React.PureComponent { /> - - Query features: - {featuresCount && Count: {featuresCount}} - ); } diff --git a/fabricexample/src/examples/FillRasterLayer/CustomVectorSource.js b/fabricexample/src/examples/FillRasterLayer/CustomVectorSource.js index d536161f3..8ee82058e 100755 --- a/fabricexample/src/examples/FillRasterLayer/CustomVectorSource.js +++ b/fabricexample/src/examples/FillRasterLayer/CustomVectorSource.js @@ -1,11 +1,9 @@ import React from 'react'; import MapboxGL from '@rnmapbox/maps'; -import { Text } from 'react-native'; import sheet from '../../styles/sheet'; import BaseExamplePropTypes from '../common/BaseExamplePropTypes'; import Page from '../common/Page'; -import Bubble from '../common/Bubble'; const styles = { boxFill: { @@ -43,7 +41,6 @@ class CustomVectorSource extends React.PureComponent { }; render() { - const { featuresCount } = this.state; return ( @@ -69,10 +66,6 @@ class CustomVectorSource extends React.PureComponent { /> - - Query features: - {featuresCount && Count: {featuresCount}} - ); } diff --git a/ios/RNMBX/RNMBXBackgroundLayerComponentView.mm b/ios/RNMBX/RNMBXBackgroundLayerComponentView.mm index 053a25b08..1508e40f6 100644 --- a/ios/RNMBX/RNMBXBackgroundLayerComponentView.mm +++ b/ios/RNMBX/RNMBXBackgroundLayerComponentView.mm @@ -3,6 +3,7 @@ #import "RNMBXBackgroundLayerComponentView.h" #import "RNMBXFabricHelpers.h" +#import #import #import @@ -34,6 +35,7 @@ - (instancetype)initWithFrame:(CGRect)frame - (void)prepareView { _view = [[RNMBXBackgroundLayer alloc] init]; + _view.bridge = [RCTBridge currentBridge]; self.contentView = _view; } diff --git a/ios/RNMBX/RNMBXCircleLayerComponentView.mm b/ios/RNMBX/RNMBXCircleLayerComponentView.mm index 3c9539e1d..b5fb96f21 100644 --- a/ios/RNMBX/RNMBXCircleLayerComponentView.mm +++ b/ios/RNMBX/RNMBXCircleLayerComponentView.mm @@ -5,6 +5,7 @@ #import #import +#import #import #import @@ -34,6 +35,7 @@ - (instancetype)initWithFrame:(CGRect)frame - (void)prepareView { _view = [[RNMBXCircleLayer alloc] init]; + _view.bridge = [RCTBridge currentBridge]; self.contentView = _view; } diff --git a/ios/RNMBX/RNMBXFillExtrusionLayerComponentView.mm b/ios/RNMBX/RNMBXFillExtrusionLayerComponentView.mm index 568081f83..4436f2a3c 100644 --- a/ios/RNMBX/RNMBXFillExtrusionLayerComponentView.mm +++ b/ios/RNMBX/RNMBXFillExtrusionLayerComponentView.mm @@ -5,6 +5,7 @@ #import #import +#import #import #import @@ -34,7 +35,8 @@ - (instancetype)initWithFrame:(CGRect)frame - (void)prepareView { _view = [[RNMBXFillExtrusionLayer alloc] init]; - self.contentView = _view; + _view.bridge = [RCTBridge currentBridge]; + self.contentView = _view; } #pragma mark - RCTComponentViewProtocol diff --git a/ios/RNMBX/RNMBXFillLayerComponentView.mm b/ios/RNMBX/RNMBXFillLayerComponentView.mm index ebd8b5c4f..7bc88827a 100644 --- a/ios/RNMBX/RNMBXFillLayerComponentView.mm +++ b/ios/RNMBX/RNMBXFillLayerComponentView.mm @@ -5,6 +5,7 @@ #import #import +#import #import #import @@ -34,6 +35,7 @@ - (instancetype)initWithFrame:(CGRect)frame - (void)prepareView { _view = [[RNMBXFillLayer alloc] init]; + _view.bridge = [RCTBridge currentBridge]; self.contentView = _view; } diff --git a/ios/RNMBX/RNMBXHeatmapLayerComponentView.mm b/ios/RNMBX/RNMBXHeatmapLayerComponentView.mm index 988c0a24a..47aa9fe54 100644 --- a/ios/RNMBX/RNMBXHeatmapLayerComponentView.mm +++ b/ios/RNMBX/RNMBXHeatmapLayerComponentView.mm @@ -5,6 +5,7 @@ #import #import +#import #import #import @@ -34,6 +35,7 @@ - (instancetype)initWithFrame:(CGRect)frame - (void)prepareView { _view = [[RNMBXHeatmapLayer alloc] init]; + _view.bridge = [RCTBridge currentBridge]; self.contentView = _view; } #pragma mark - RCTComponentViewProtocol diff --git a/ios/RNMBX/RNMBXImageSource.swift b/ios/RNMBX/RNMBXImageSource.swift index 0bddcf82e..b60dee623 100644 --- a/ios/RNMBX/RNMBXImageSource.swift +++ b/ios/RNMBX/RNMBXImageSource.swift @@ -1,9 +1,9 @@ import MapboxMaps @objc -class RNMBXImageSource : RNMBXSource { +public class RNMBXImageSource : RNMBXSource { - @objc var url: String? = nil { + @objc public var url: String? = nil { didSet { if var source = source as? ImageSource { source.url = url @@ -14,7 +14,7 @@ class RNMBXImageSource : RNMBXSource { } } - @objc var coordinates: [[NSNumber]]? = nil { + @objc public var coordinates: [[NSNumber]]? = nil { didSet { if var source = source as? ImageSource { if let coordinates = coordinates { diff --git a/ios/RNMBX/RNMBXImageSourceComponentView.h b/ios/RNMBX/RNMBXImageSourceComponentView.h new file mode 100644 index 000000000..be6a0404b --- /dev/null +++ b/ios/RNMBX/RNMBXImageSourceComponentView.h @@ -0,0 +1,15 @@ +#ifdef RCT_NEW_ARCH_ENABLED + +#import + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface RNMBXImageSourceComponentView : RCTViewComponentView +@end + +NS_ASSUME_NONNULL_END + +#endif // RCT_NEW_ARCH_ENABLED diff --git a/ios/RNMBX/RNMBXImageSourceComponentView.mm b/ios/RNMBX/RNMBXImageSourceComponentView.mm new file mode 100644 index 000000000..91616b266 --- /dev/null +++ b/ios/RNMBX/RNMBXImageSourceComponentView.mm @@ -0,0 +1,100 @@ +#ifdef RCT_NEW_ARCH_ENABLED + +#import "RNMBXImageSourceComponentView.h" +#import "RNMBXFabricHelpers.h" + +#import +#import + +#import +#import +#import +#import + +using namespace facebook::react; + +@interface RNMBXImageSourceComponentView () +@end + +@implementation RNMBXImageSourceComponentView { + RNMBXImageSource *_view; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + [self prepareView]; + } + + return self; +} + +- (void)prepareView +{ + _view = [[RNMBXImageSource alloc] init]; + self.contentView = _view; +} + +- (void)prepareForRecycle +{ + [super prepareForRecycle]; + [self prepareView]; +} + +- (void)mountChildComponentView:(UIView *)childComponentView index:(NSInteger)index +{ + if ([childComponentView isKindOfClass:[RCTViewComponentView class]]) { + [_view insertReactSubviewInternal:((RCTViewComponentView *)childComponentView).contentView at:index]; + } else { + RCTLogError(@"Tried to add view that is not RCTViewComponentView: %@", childComponentView); + } +} + +- (void)unmountChildComponentView:(UIView *)childComponentView index:(NSInteger)index +{ + if ([childComponentView isKindOfClass:[RCTViewComponentView class]]) { + [_view removeReactSubviewInternal:((RCTViewComponentView *)childComponentView).contentView]; + } else { + RCTLogError(@"Tried to remove view that is not RCTViewComponentView: %@", childComponentView); + } +} + +#pragma mark - RCTComponentViewProtocol + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps +{ + const auto &newProps = *std::static_pointer_cast(props); + id idx = RNMBXConvertFollyDynamicToId(newProps.id); + if (idx != nil) { + _view.id = idx; + } + id existing = RNMBXConvertFollyDynamicToId(newProps.existing); + if (existing != nil) { + _view.existing = existing; + } + id url = RNMBXConvertFollyDynamicToId(newProps.url); + if (url != nil) { + _view.url = url; + } + id coordinates = RNMBXConvertFollyDynamicToId(newProps.coordinates); + if (coordinates != nil) { + _view.coordinates = coordinates; + } + [super updateProps:props oldProps:oldProps]; +} + +@end + +Class RNMBXImageSourceCls(void) +{ + return RNMBXImageSourceComponentView.class; +} + +#endif // RCT_NEW_ARCH_ENABLED diff --git a/ios/RNMBX/RNMBXImageSourceManager.m b/ios/RNMBX/RNMBXImageSourceViewManager.m similarity index 71% rename from ios/RNMBX/RNMBXImageSourceManager.m rename to ios/RNMBX/RNMBXImageSourceViewManager.m index 82545c4d9..5d4bc4a2b 100644 --- a/ios/RNMBX/RNMBXImageSourceManager.m +++ b/ios/RNMBX/RNMBXImageSourceViewManager.m @@ -1,7 +1,7 @@ #import #import -@interface RCT_EXTERN_MODULE(RNMBXImageSourceManager, RCTViewManager) +@interface RCT_EXTERN_REMAP_MODULE(RNMBXImageSource, RNMBXImageSourceViewManager, RCTViewManager) RCT_EXPORT_VIEW_PROPERTY(id, NSString) RCT_EXPORT_VIEW_PROPERTY(existing, BOOL) diff --git a/ios/RNMBX/RNMBXImageSourceManager.swift b/ios/RNMBX/RNMBXImageSourceViewManager.swift similarity index 65% rename from ios/RNMBX/RNMBXImageSourceManager.swift rename to ios/RNMBX/RNMBXImageSourceViewManager.swift index 208acaa62..d86b4f77a 100644 --- a/ios/RNMBX/RNMBXImageSourceManager.swift +++ b/ios/RNMBX/RNMBXImageSourceViewManager.swift @@ -1,5 +1,5 @@ -@objc(RNMBXImageSourceManager) -class RNMBXImageSourceManager: RCTViewManager { +@objc(RNMBXImageSourceViewManager) +class RNMBXImageSourceViewManager: RCTViewManager { @objc override static func requiresMainQueueSetup() -> Bool { return true diff --git a/ios/RNMBX/RNMBXInteractiveElement.swift b/ios/RNMBX/RNMBXInteractiveElement.swift index d7aa0c627..1bdca463e 100644 --- a/ios/RNMBX/RNMBXInteractiveElement.swift +++ b/ios/RNMBX/RNMBXInteractiveElement.swift @@ -1,21 +1,21 @@ import MapboxMaps @objc -class RNMBXInteractiveElement : UIView, RNMBXMapComponent { +public class RNMBXInteractiveElement : UIView, RNMBXMapComponent { weak var map : RNMBXMapView? = nil static let hitboxDefault = 44.0 - @objc var draggable: Bool = false + @objc public var draggable: Bool = false - @objc var hasPressListener: Bool = false + @objc public var hasPressListener: Bool = false - @objc var hitbox : [String:NSNumber] = [ + @objc public var hitbox : [String:NSNumber] = [ "width": NSNumber(value: hitboxDefault), "height": NSNumber(value: hitboxDefault) ] - @objc var id: String! = nil { + @objc public var id: String! = nil { willSet { if id != nil && newValue != id { Logger.log(level:.warn, message: "Changing id from: \(optional: id) to \(optional: newValue), changing of id is supported") @@ -29,9 +29,9 @@ class RNMBXInteractiveElement : UIView, RNMBXMapComponent { } } - @objc var onDragStart: RCTBubblingEventBlock? = nil + @objc public var onDragStart: RCTBubblingEventBlock? = nil - @objc var onPress: RCTBubblingEventBlock? = nil + @objc public var onPress: RCTBubblingEventBlock? = nil func getLayerIDs() -> [String] { return [] diff --git a/ios/RNMBX/RNMBXLayer.swift b/ios/RNMBX/RNMBXLayer.swift index 5ef7ce2e4..16587848f 100644 --- a/ios/RNMBX/RNMBXLayer.swift +++ b/ios/RNMBX/RNMBXLayer.swift @@ -15,7 +15,7 @@ func styleLayerExists(_ style: Style, id: String) -> Bool { @objc(RNMBXLayer) public class RNMBXLayer : UIView, RNMBXMapComponent, RNMBXSourceConsumer { - weak var bridge : RCTBridge? = nil + @objc public weak var bridge : RCTBridge? = nil var waitingForID: String? = nil diff --git a/ios/RNMBX/RNMBXLineLayerComponentView.mm b/ios/RNMBX/RNMBXLineLayerComponentView.mm index 7b9e329dd..27e19e026 100644 --- a/ios/RNMBX/RNMBXLineLayerComponentView.mm +++ b/ios/RNMBX/RNMBXLineLayerComponentView.mm @@ -5,6 +5,7 @@ #import #import +#import #import #import @@ -34,6 +35,7 @@ - (instancetype)initWithFrame:(CGRect)frame - (void)prepareView { _view = [[RNMBXLineLayer alloc] init]; + _view.bridge = [RCTBridge currentBridge]; self.contentView = _view; } diff --git a/ios/RNMBX/RNMBXMapFeatureView.h b/ios/RNMBX/RNMBXMapFeatureView.h new file mode 100644 index 000000000..7557faae5 --- /dev/null +++ b/ios/RNMBX/RNMBXMapFeatureView.h @@ -0,0 +1,7 @@ +#import + +@protocol RNMBXMapFeatureView + +@property (strong, nonatomic) UIView* mapFeature; + +@end diff --git a/ios/RNMBX/RNMBXRasterDemSource.swift b/ios/RNMBX/RNMBXRasterDemSource.swift index d4f2e316d..b352a1367 100644 --- a/ios/RNMBX/RNMBXRasterDemSource.swift +++ b/ios/RNMBX/RNMBXRasterDemSource.swift @@ -1,23 +1,23 @@ import MapboxMaps @objc -class RNMBXRasterDemSource : RNMBXSource { +public class RNMBXRasterDemSource : RNMBXSource { typealias SourceType = RasterDemSource @objc - var url: String? = nil + public var url: String? = nil @objc - var tileUrlTemplates: [String]? = nil + public var tileUrlTemplates: [String]? = nil @objc - var tileSize : NSNumber? = nil + public var tileSize : NSNumber? = nil @objc - var maxZoomLevel : NSNumber? = nil + public var maxZoomLevel : NSNumber? = nil @objc - var minZoomLevel : NSNumber? = nil + public var minZoomLevel : NSNumber? = nil @objc static func requiresMainQueueSetup() -> Bool { diff --git a/ios/RNMBX/RNMBXRasterDemSourceComponentView.h b/ios/RNMBX/RNMBXRasterDemSourceComponentView.h new file mode 100644 index 000000000..f1507163e --- /dev/null +++ b/ios/RNMBX/RNMBXRasterDemSourceComponentView.h @@ -0,0 +1,17 @@ +#ifdef RCT_NEW_ARCH_ENABLED + +#import + +#import +#import + +#import "RNMBXMapFeatureView.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface RNMBXRasterDemSourceComponentView : RCTViewComponentView +@end + +NS_ASSUME_NONNULL_END + +#endif // RCT_NEW_ARCH_ENABLED diff --git a/ios/RNMBX/RNMBXRasterDemSourceComponentView.mm b/ios/RNMBX/RNMBXRasterDemSourceComponentView.mm new file mode 100644 index 000000000..e76c8fe00 --- /dev/null +++ b/ios/RNMBX/RNMBXRasterDemSourceComponentView.mm @@ -0,0 +1,116 @@ +#ifdef RCT_NEW_ARCH_ENABLED + +#import "RNMBXRasterDemSourceComponentView.h" +#import "RNMBXFabricHelpers.h" + +#import +#import + +#import +#import +#import +#import + +using namespace facebook::react; + +@interface RNMBXRasterDemSourceComponentView () +@end + +@implementation RNMBXRasterDemSourceComponentView { + RNMBXRasterDemSource *_view; +} + +@synthesize mapFeature; + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + [self prepareView]; + } + + return self; +} + +- (void)prepareView +{ + _view = [[RNMBXRasterDemSource alloc] init]; + self.contentView = _view; + self.mapFeature = _view; +} + +- (void)prepareForRecycle +{ + [super prepareForRecycle]; + [self prepareView]; +} + +- (void)mountChildComponentView:(UIView *)childComponentView index:(NSInteger)index +{ + if ([childComponentView isKindOfClass:[RCTViewComponentView class]]) { + [_view insertReactSubviewInternal:((RCTViewComponentView *)childComponentView).contentView at:index]; + } else { + RCTLogError(@"Tried to add view that is not RCTViewComponentView: %@", childComponentView); + } +} + +- (void)unmountChildComponentView:(UIView *)childComponentView index:(NSInteger)index +{ + if ([childComponentView isKindOfClass:[RCTViewComponentView class]]) { + [_view removeReactSubviewInternal:((RCTViewComponentView *)childComponentView).contentView]; + } else { + RCTLogError(@"Tried to remove view that is not RCTViewComponentView: %@", childComponentView); + } +} + +#pragma mark - RCTComponentViewProtocol + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps +{ + const auto &newProps = *std::static_pointer_cast(props); + id idx = RNMBXConvertFollyDynamicToId(newProps.id); + if (idx != nil) { + _view.id = idx; + } + id existing = RNMBXConvertFollyDynamicToId(newProps.existing); + if (existing != nil) { + _view.existing = existing; + } + id url = RNMBXConvertFollyDynamicToId(newProps.url); + if (url != nil) { + _view.url = url; + } + id tileUrlTemplates = RNMBXConvertFollyDynamicToId(newProps.tileUrlTemplates); + if (tileUrlTemplates != nil) { + _view.tileUrlTemplates = tileUrlTemplates; + } + id minZoomLevel = RNMBXConvertFollyDynamicToId(newProps.minZoomLevel); + if (minZoomLevel != nil) { + _view.minZoomLevel = minZoomLevel; + } + id maxZoomLevel = RNMBXConvertFollyDynamicToId(newProps.maxZoomLevel); + if (maxZoomLevel != nil) { + _view.maxZoomLevel = maxZoomLevel; + } + id tileSize = RNMBXConvertFollyDynamicToId(newProps.tileSize); + if (tileSize != nil) { + _view.tileSize = tileSize; + } + + [super updateProps:props oldProps:oldProps]; +} + +@end + +Class RNMBXRasterDemSourceCls(void) +{ + return RNMBXRasterDemSourceComponentView.class; +} + +#endif // RCT_NEW_ARCH_ENABLED diff --git a/ios/RNMBX/RNMBXRasterDemSourceManager.m b/ios/RNMBX/RNMBXRasterDemSourceViewManager.m similarity index 52% rename from ios/RNMBX/RNMBXRasterDemSourceManager.m rename to ios/RNMBX/RNMBXRasterDemSourceViewManager.m index cb80c730c..5bbfd3b23 100644 --- a/ios/RNMBX/RNMBXRasterDemSourceManager.m +++ b/ios/RNMBX/RNMBXRasterDemSourceViewManager.m @@ -1,7 +1,7 @@ #import #import -@interface RCT_EXTERN_MODULE(RNMBXRasterDemSourceManager, RCTViewManager) +@interface RCT_EXTERN_REMAP_MODULE(RNMBXRasterDemSource, RNMBXRasterDemSourceViewManager, RCTViewManager) RCT_EXPORT_VIEW_PROPERTY(id, NSString) RCT_EXPORT_VIEW_PROPERTY(existing, BOOL) @@ -11,11 +11,5 @@ @interface RCT_EXTERN_MODULE(RNMBXRasterDemSourceManager, RCTViewManager) RCT_EXPORT_VIEW_PROPERTY(minZoomLevel, NSNumber) RCT_EXPORT_VIEW_PROPERTY(maxZoomLevel, NSNumber) RCT_EXPORT_VIEW_PROPERTY(tileSize, NSNumber) -RCT_EXPORT_VIEW_PROPERTY(attribution, NSString) -RCT_EXPORT_VIEW_PROPERTY(encoding, NSString) -RCT_EXPORT_VIEW_PROPERTY(volatile, NSNumber) -RCT_EXPORT_VIEW_PROPERTY(prefetchZoomDelta, NSNumber) -RCT_EXPORT_VIEW_PROPERTY(minimumTileUpdateInterval, NSNumber) -RCT_EXPORT_VIEW_PROPERTY(maxOverscaleFactorForParentTiles, NSNumber) @end diff --git a/ios/RNMBX/RNMBXRasterDemSourceManager.swift b/ios/RNMBX/RNMBXRasterDemSourceViewManager.swift similarity index 63% rename from ios/RNMBX/RNMBXRasterDemSourceManager.swift rename to ios/RNMBX/RNMBXRasterDemSourceViewManager.swift index 272983835..ea7f2e84b 100644 --- a/ios/RNMBX/RNMBXRasterDemSourceManager.swift +++ b/ios/RNMBX/RNMBXRasterDemSourceViewManager.swift @@ -1,5 +1,5 @@ -@objc(RNMBXRasterDemSourceManager) -class RNMBXRasterDemSourceManager: RCTViewManager { +@objc(RNMBXRasterDemSourceViewManager) +class RNMBXRasterDemSourceViewManager: RCTViewManager { @objc override static func requiresMainQueueSetup() -> Bool { return true diff --git a/ios/RNMBX/RNMBXRasterLayerComponentView.mm b/ios/RNMBX/RNMBXRasterLayerComponentView.mm index a25c812be..0db3d386d 100644 --- a/ios/RNMBX/RNMBXRasterLayerComponentView.mm +++ b/ios/RNMBX/RNMBXRasterLayerComponentView.mm @@ -5,6 +5,7 @@ #import #import +#import #import #import @@ -34,6 +35,7 @@ - (instancetype)initWithFrame:(CGRect)frame - (void)prepareView { _view = [[RNMBXRasterLayer alloc] init]; + _view.bridge = [RCTBridge currentBridge]; self.contentView = _view; } diff --git a/ios/RNMBX/RNMBXRasterSource.swift b/ios/RNMBX/RNMBXRasterSource.swift index 9916d2db6..d40732c1b 100644 --- a/ios/RNMBX/RNMBXRasterSource.swift +++ b/ios/RNMBX/RNMBXRasterSource.swift @@ -1,20 +1,20 @@ import MapboxMaps @objc -class RNMBXRasterSource : RNMBXSource { +public class RNMBXRasterSource : RNMBXSource { typealias SourceType = RasterSource - @objc var url: String? = nil + @objc public var url: String? = nil - @objc var tileUrlTemplates: [String]? = nil + @objc public var tileUrlTemplates: [String]? = nil - @objc var minZoomLevel: NSNumber? - @objc var maxZoomLevel: NSNumber? - @objc var tileSize: NSNumber? + @objc public var minZoomLevel: NSNumber? + @objc public var maxZoomLevel: NSNumber? + @objc public var tileSize: NSNumber? - @objc var tms: Bool = false + @objc public var tms: Bool = false - @objc var attribution: String? + @objc public var attribution: String? override func makeSource() -> Source { diff --git a/ios/RNMBX/RNMBXRasterSourceComponentView.h b/ios/RNMBX/RNMBXRasterSourceComponentView.h new file mode 100644 index 000000000..4f5c370c0 --- /dev/null +++ b/ios/RNMBX/RNMBXRasterSourceComponentView.h @@ -0,0 +1,17 @@ +#ifdef RCT_NEW_ARCH_ENABLED + +#import + +#import +#import + +#import "RNMBXMapFeatureView.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface RNMBXRasterSourceComponentView : RCTViewComponentView +@end + +NS_ASSUME_NONNULL_END + +#endif // RCT_NEW_ARCH_ENABLED diff --git a/ios/RNMBX/RNMBXRasterSourceComponentView.mm b/ios/RNMBX/RNMBXRasterSourceComponentView.mm new file mode 100644 index 000000000..6d180fba3 --- /dev/null +++ b/ios/RNMBX/RNMBXRasterSourceComponentView.mm @@ -0,0 +1,124 @@ +#ifdef RCT_NEW_ARCH_ENABLED + +#import "RNMBXRasterSourceComponentView.h" +#import "RNMBXFabricHelpers.h" + +#import +#import + +#import +#import +#import +#import + +using namespace facebook::react; + +@interface RNMBXRasterSourceComponentView () +@end + +@implementation RNMBXRasterSourceComponentView { + RNMBXRasterSource *_view; +} + +@synthesize mapFeature; + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + [self prepareView]; + } + + return self; +} + +- (void)prepareView +{ + _view = [[RNMBXRasterSource alloc] init]; + self.contentView = _view; + self.mapFeature = _view; +} + +- (void)prepareForRecycle +{ + [super prepareForRecycle]; + [self prepareView]; +} + +- (void)mountChildComponentView:(UIView *)childComponentView index:(NSInteger)index +{ + if ([childComponentView isKindOfClass:[RCTViewComponentView class]]) { + [_view insertReactSubviewInternal:((RCTViewComponentView *)childComponentView).contentView at:index]; + } else { + RCTLogError(@"Tried to add view that is not RCTViewComponentView: %@", childComponentView); + } +} + +- (void)unmountChildComponentView:(UIView *)childComponentView index:(NSInteger)index +{ + if ([childComponentView isKindOfClass:[RCTViewComponentView class]]) { + [_view removeReactSubviewInternal:((RCTViewComponentView *)childComponentView).contentView]; + } else { + RCTLogError(@"Tried to remove view that is not RCTViewComponentView: %@", childComponentView); + } +} + +#pragma mark - RCTComponentViewProtocol + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps +{ + const auto &newProps = *std::static_pointer_cast(props); + id idx = RNMBXConvertFollyDynamicToId(newProps.id); + if (idx != nil) { + _view.id = idx; + } + id existing = RNMBXConvertFollyDynamicToId(newProps.existing); + if (existing != nil) { + _view.existing = existing; + } + id url = RNMBXConvertFollyDynamicToId(newProps.url); + if (url != nil) { + _view.url = url; + } + id tileUrlTemplates = RNMBXConvertFollyDynamicToId(newProps.tileUrlTemplates); + if (tileUrlTemplates != nil) { + _view.tileUrlTemplates = tileUrlTemplates; + } + id minZoomLevel = RNMBXConvertFollyDynamicToId(newProps.minZoomLevel); + if (minZoomLevel != nil) { + _view.minZoomLevel = minZoomLevel; + } + id maxZoomLevel = RNMBXConvertFollyDynamicToId(newProps.maxZoomLevel); + if (maxZoomLevel != nil) { + _view.maxZoomLevel = maxZoomLevel; + } + id tileSize = RNMBXConvertFollyDynamicToId(newProps.tileSize); + if (tileSize != nil) { + _view.tileSize = tileSize; + } + id tms = RNMBXConvertFollyDynamicToId(newProps.tms); + if (tms != nil) { + _view.tms = tms; + } + id attribution = RNMBXConvertFollyDynamicToId(newProps.attribution); + if (attribution != nil) { + _view.attribution = attribution; + } + + [super updateProps:props oldProps:oldProps]; +} + +@end + +Class RNMBXRasterSourceCls(void) +{ + return RNMBXRasterSourceComponentView.class; +} + +#endif // RCT_NEW_ARCH_ENABLED diff --git a/ios/RNMBX/RNMBXRasterSourceManager.m b/ios/RNMBX/RNMBXRasterSourceViewManager.m similarity index 82% rename from ios/RNMBX/RNMBXRasterSourceManager.m rename to ios/RNMBX/RNMBXRasterSourceViewManager.m index a890c6802..427c90a0a 100644 --- a/ios/RNMBX/RNMBXRasterSourceManager.m +++ b/ios/RNMBX/RNMBXRasterSourceViewManager.m @@ -1,7 +1,7 @@ #import #import -@interface RCT_EXTERN_MODULE(RNMBXRasterSourceManager, RCTViewManager) +@interface RCT_EXTERN_REMAP_MODULE(RNMBXRasterSource, RNMBXRasterSourceViewManager, RCTViewManager) RCT_EXPORT_VIEW_PROPERTY(id, NSString) RCT_EXPORT_VIEW_PROPERTY(existing, BOOL) diff --git a/ios/RNMBX/RNMBXRasterSourceManager.swift b/ios/RNMBX/RNMBXRasterSourceViewManager.swift similarity index 68% rename from ios/RNMBX/RNMBXRasterSourceManager.swift rename to ios/RNMBX/RNMBXRasterSourceViewManager.swift index 5c42c7265..a80326ab7 100644 --- a/ios/RNMBX/RNMBXRasterSourceManager.swift +++ b/ios/RNMBX/RNMBXRasterSourceViewManager.swift @@ -1,8 +1,8 @@ import Foundation import MapboxMaps -@objc(RNMBXRasterSourceManager) -class RNMBXRasterSourceManager : RCTViewManager { +@objc(RNMBXRasterSourceViewManager) +class RNMBXRasterSourceViewManager : RCTViewManager { @objc override static func requiresMainQueueSetup() -> Bool { return true diff --git a/ios/RNMBX/RNMBXShapeSource.swift b/ios/RNMBX/RNMBXShapeSource.swift index 91d55bfff..0b7d1049a 100644 --- a/ios/RNMBX/RNMBXShapeSource.swift +++ b/ios/RNMBX/RNMBXShapeSource.swift @@ -2,8 +2,8 @@ import MapboxMaps import Turf @objc -class RNMBXShapeSource : RNMBXSource { - @objc var url : String? { +public class RNMBXShapeSource : RNMBXSource { + @objc public var url : String? { didSet { parseJSON(url) { [weak self] result in guard let self = self else { return } @@ -23,7 +23,7 @@ class RNMBXShapeSource : RNMBXSource { } } - @objc var shape : String? { + @objc public var shape : String? { didSet { logged("RNMBXShapeSource.updateShape") { let obj : GeoJSONObject = try parse(shape) @@ -37,9 +37,9 @@ class RNMBXShapeSource : RNMBXSource { } } - @objc var cluster : NSNumber? - @objc var clusterRadius : NSNumber? - @objc var clusterMaxZoomLevel : NSNumber? { + @objc public var cluster : NSNumber? + @objc public var clusterRadius : NSNumber? + @objc public var clusterMaxZoomLevel : NSNumber? { didSet { logged("RNMBXShapeSource.clusterMaxZoomLevel") { if let number = clusterMaxZoomLevel?.doubleValue { @@ -52,12 +52,12 @@ class RNMBXShapeSource : RNMBXSource { } } } - @objc var clusterProperties : [String: [Any]]?; + @objc public var clusterProperties : [String: [Any]]?; - @objc var maxZoomLevel : NSNumber? - @objc var buffer : NSNumber? - @objc var tolerance : NSNumber? - @objc var lineMetrics : NSNumber? + @objc public var maxZoomLevel : NSNumber? + @objc public var buffer : NSNumber? + @objc public var tolerance : NSNumber? + @objc public var lineMetrics : NSNumber? override func sourceType() -> Source.Type { return GeoJSONSource.self diff --git a/ios/RNMBX/RNMBXShapeSourceComponentView.h b/ios/RNMBX/RNMBXShapeSourceComponentView.h new file mode 100644 index 000000000..12535595a --- /dev/null +++ b/ios/RNMBX/RNMBXShapeSourceComponentView.h @@ -0,0 +1,17 @@ +#ifdef RCT_NEW_ARCH_ENABLED + +#import + +#import +#import + +#import "RNMBXMapFeatureView.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface RNMBXShapeSourceComponentView : RCTViewComponentView +@end + +NS_ASSUME_NONNULL_END + +#endif // RCT_NEW_ARCH_ENABLED diff --git a/ios/RNMBX/RNMBXShapeSourceComponentView.mm b/ios/RNMBX/RNMBXShapeSourceComponentView.mm new file mode 100644 index 000000000..243229e2d --- /dev/null +++ b/ios/RNMBX/RNMBXShapeSourceComponentView.mm @@ -0,0 +1,153 @@ +#ifdef RCT_NEW_ARCH_ENABLED + +#import "RNMBXShapeSourceComponentView.h" +#import "RNMBXFabricHelpers.h" + +#import +#import + +#import +#import +#import +#import + +using namespace facebook::react; + +@interface RNMBXShapeSourceComponentView () +@end + +@implementation RNMBXShapeSourceComponentView { + RNMBXShapeSource *_view; +} + +@synthesize mapFeature; + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + [self prepareView]; + } + + return self; +} + +- (void)prepareView +{ + _view = [[RNMBXShapeSource alloc] init]; + + + // capture weak self reference to prevent retain cycle + __weak __typeof__(self) weakSelf = self; + + [_view setOnPress:^(NSDictionary* event) { + __typeof__(self) strongSelf = weakSelf; + + if (strongSelf != nullptr && strongSelf->_eventEmitter != nullptr) { + const auto [type, json] = RNMBXStringifyEventData(event); + std::dynamic_pointer_cast(strongSelf->_eventEmitter)->onMapboxShapeSourcePress({type, json}); + } + }]; + + self.contentView = _view; + self.mapFeature = _view; +} + +- (void)prepareForRecycle +{ + [super prepareForRecycle]; + [self prepareView]; +} + +- (void)mountChildComponentView:(UIView *)childComponentView index:(NSInteger)index +{ + if ([childComponentView isKindOfClass:[RCTViewComponentView class]]) { + [_view insertReactSubviewInternal:((RCTViewComponentView *)childComponentView).contentView at:index]; + } else { + RCTLogError(@"Tried to add view that is not RCTViewComponentView: %@", childComponentView); + } +} + +- (void)unmountChildComponentView:(UIView *)childComponentView index:(NSInteger)index +{ + if ([childComponentView isKindOfClass:[RCTViewComponentView class]]) { + [_view removeReactSubviewInternal:((RCTViewComponentView *)childComponentView).contentView]; + } else { + RCTLogError(@"Tried to remove view that is not RCTViewComponentView: %@", childComponentView); + } +} + +#pragma mark - RCTComponentViewProtocol + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps +{ + const auto &newProps = *std::static_pointer_cast(props); + id idx = RNMBXConvertFollyDynamicToId(newProps.id); + if (idx != nil) { + _view.id = idx; + } + id existing = RNMBXConvertFollyDynamicToId(newProps.existing); + if (existing != nil) { + _view.existing = existing; + } + id shape = RNMBXConvertFollyDynamicToId(newProps.shape); + if (shape != nil) { + _view.shape = shape; + } + id cluster = RNMBXConvertFollyDynamicToId(newProps.cluster); + if (cluster != nil) { + _view.cluster = cluster; + } + id clusterRadius = RNMBXConvertFollyDynamicToId(newProps.clusterRadius); + if (clusterRadius != nil) { + _view.clusterRadius = clusterRadius; + } + id clusterMaxZoomLevel = RNMBXConvertFollyDynamicToId(newProps.clusterMaxZoomLevel); + if (clusterMaxZoomLevel != nil) { + _view.clusterMaxZoomLevel = clusterMaxZoomLevel; + } + id clusterProperties = RNMBXConvertFollyDynamicToId(newProps.clusterProperties); + if (clusterProperties != nil) { + _view.clusterProperties = clusterProperties; + } + id maxZoomLevel = RNMBXConvertFollyDynamicToId(newProps.maxZoomLevel); + if (maxZoomLevel != nil) { + _view.maxZoomLevel = maxZoomLevel; + } + id buffer = RNMBXConvertFollyDynamicToId(newProps.buffer); + if (buffer != nil) { + _view.buffer = buffer; + } + id tolerance = RNMBXConvertFollyDynamicToId(newProps.tolerance); + if (tolerance != nil) { + _view.tolerance = tolerance; + } + id lineMetrics = RNMBXConvertFollyDynamicToId(newProps.lineMetrics); + if (lineMetrics != nil) { + _view.lineMetrics = lineMetrics; + } + id hasPressListener = RNMBXConvertFollyDynamicToId(newProps.hasPressListener); + if (hasPressListener != nil) { + _view.hasPressListener = hasPressListener; + } + id hitbox = RNMBXConvertFollyDynamicToId(newProps.hitbox); + if (hitbox != nil) { + _view.hitbox = hitbox; + } + [super updateProps:props oldProps:oldProps]; +} + +@end + +Class RNMBXShapeSourceCls(void) +{ + return RNMBXShapeSourceComponentView.class; +} + +#endif // RCT_NEW_ARCH_ENABLED diff --git a/ios/RNMBX/RNMBXShapeSourceManager.m b/ios/RNMBX/RNMBXShapeSourceManager.m deleted file mode 100644 index 79fcb99b3..000000000 --- a/ios/RNMBX/RNMBXShapeSourceManager.m +++ /dev/null @@ -1,45 +0,0 @@ -#import -#import - -@interface -RCT_EXTERN_REMAP_MODULE(RNMBXShapeSource, RNMBXShapeSourceManager, RCTViewManager) - -RCT_EXPORT_VIEW_PROPERTY(id, NSString) -RCT_EXPORT_VIEW_PROPERTY(existing, BOOL) -RCT_EXPORT_VIEW_PROPERTY(url, NSString) -RCT_EXPORT_VIEW_PROPERTY(shape, NSString) - -RCT_EXPORT_VIEW_PROPERTY(cluster, NSNumber) -RCT_EXPORT_VIEW_PROPERTY(clusterRadius, NSNumber) -RCT_EXPORT_VIEW_PROPERTY(clusterMaxZoomLevel, NSNumber) -RCT_EXPORT_VIEW_PROPERTY(clusterProperties, NSDictionary) -RCT_EXPORT_VIEW_PROPERTY(maxZoomLevel, NSNumber) -RCT_EXPORT_VIEW_PROPERTY(buffer, NSNumber) -RCT_EXPORT_VIEW_PROPERTY(tolerance, NSNumber) -RCT_EXPORT_VIEW_PROPERTY(lineMetrics, NSNumber) -RCT_EXPORT_VIEW_PROPERTY(images, NSDictionary) -RCT_EXPORT_VIEW_PROPERTY(nativeImages, NSArray) -RCT_EXPORT_VIEW_PROPERTY(hasPressListener, BOOL) -RCT_EXPORT_VIEW_PROPERTY(hitbox, NSDictionary) -RCT_REMAP_VIEW_PROPERTY(onMapboxShapeSourcePress, onPress, RCTBubblingEventBlock) - - - -RCT_EXTERN_METHOD(getClusterExpansionZoom:(nonnull NSNumber*)reactTag - featureJSON:(nonnull NSString*)featureJSON - resolver:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) - -RCT_EXTERN_METHOD(getClusterLeaves:(nonnull NSNumber*)reactTag - featureJSON:(nonnull NSString*)featureJSON - number:(NSUInteger) number - offset:(NSUInteger) offset - resolver:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) - -RCT_EXTERN_METHOD(getClusterChildren:(nonnull NSNumber*)reactTag - featureJSON:(nonnull NSString*)featureJSON - resolver:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) - -@end diff --git a/ios/RNMBX/RNMBXShapeSourceModule.h b/ios/RNMBX/RNMBXShapeSourceModule.h new file mode 100644 index 000000000..9f2ac26ce --- /dev/null +++ b/ios/RNMBX/RNMBXShapeSourceModule.h @@ -0,0 +1,18 @@ +#import +#import + +#ifdef RCT_NEW_ARCH_ENABLED +#import "rnmapbox_maps_specs.h" +#else +#import +#endif + +@interface RNMBXShapeSourceModule : NSObject +#ifdef RCT_NEW_ARCH_ENABLED + +#else + +#endif + +@end + diff --git a/ios/RNMBX/RNMBXShapeSourceModule.mm b/ios/RNMBX/RNMBXShapeSourceModule.mm new file mode 100644 index 000000000..fec77f3bd --- /dev/null +++ b/ios/RNMBX/RNMBXShapeSourceModule.mm @@ -0,0 +1,87 @@ +#import +#import +#import + +#import "RNMBXShapeSourceModule.h" +#ifdef RCT_NEW_ARCH_ENABLED +#import "RNMBXShapeSourceComponentView.h" +#endif // RCT_NEW_ARCH_ENABLED + +// needed for compilation for some reason +#import +#import + +@interface MapView : UIView +@end + +#import + + +@implementation RNMBXShapeSourceModule + +RCT_EXPORT_MODULE(); + +#ifdef RCT_NEW_ARCH_ENABLED +@synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED; +#endif // RCT_NEW_ARCH_ENABLED +@synthesize bridge = _bridge; + +- (dispatch_queue_t)methodQueue +{ + // It seems that due to how UIBlocks work with uiManager, we need to call the methods there + // for the blocks to be dispatched before the batch is completed + return RCTGetUIManagerQueue(); +} + +- (void)withShapeSource:(nonnull NSNumber*)viewRef block:(void (^)(RNMBXShapeSource *))block reject:(RCTPromiseRejectBlock)reject methodName:(NSString *)methodName +{ +#ifdef RCT_NEW_ARCH_ENABLED + [self.viewRegistry_DEPRECATED addUIBlock:^(RCTViewRegistry *viewRegistry) { + RNMBXShapeSourceComponentView *componentView = [self.viewRegistry_DEPRECATED viewForReactTag:viewRef]; + RNMBXShapeSource *view = componentView.contentView; + +#else + [self.bridge.uiManager + addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { + RNMBXShapeSource *view = [uiManager viewForReactTag:viewRef]; +#endif // RCT_NEW_ARCH_ENABLED + if (view != nil) { + block(view); + } else { + reject(methodName, [NSString stringWithFormat:@"Unknown reactTag: %@", viewRef], nil); + } + }]; +} + + +RCT_EXPORT_METHOD(getClusterChildren:(nonnull NSNumber *)viewRef featureJSON:(NSString *)featureJSON resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) +{ + [self withShapeSource:viewRef block:^(RNMBXShapeSource *view) { + [RNMBXShapeSourceViewManager getClusterChildrenWithShapeSource:view featureJSON:featureJSON resolver:resolve rejecter:reject]; + } reject:reject methodName:@"getClusterChildren"]; +} + +RCT_EXPORT_METHOD(getClusterLeaves:(nonnull NSNumber *)viewRef featureJSON:(NSString *)featureJSON number:(double)number offset:(double)offset resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) +{ + [self withShapeSource:viewRef block:^(RNMBXShapeSource *view) { + [RNMBXShapeSourceViewManager getClusterLeavesWithShapeSource:view featureJSON:featureJSON number:number offset:offset resolver:resolve rejecter:reject]; + } reject:reject methodName:@"getClusterLeaves"]; +} + +RCT_EXPORT_METHOD(getClusterExpansionZoom:(nonnull NSNumber *)viewRef featureJSON:(NSString *)featureJSON resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) +{ + [self withShapeSource:viewRef block:^(RNMBXShapeSource *view) { + [RNMBXShapeSourceViewManager getClusterExpansionZoomWithShapeSource:view featureJSON:featureJSON resolver:resolve rejecter:reject]; + } reject:reject methodName:@"getClusterExpansionZoom"]; +} + +// Thanks to this guard, we won't compile this code when we build for the old architecture. +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params +{ + return std::make_shared(params); +} +#endif // RCT_NEW_ARCH_ENABLED + +@end diff --git a/ios/RNMBX/RNMBXShapeSourceViewManager.m b/ios/RNMBX/RNMBXShapeSourceViewManager.m new file mode 100644 index 000000000..b87592fcd --- /dev/null +++ b/ios/RNMBX/RNMBXShapeSourceViewManager.m @@ -0,0 +1,26 @@ +#import +#import + +@interface +RCT_EXTERN_REMAP_MODULE(RNMBXShapeSource, RNMBXShapeSourceViewManager, RCTViewManager) + +RCT_EXPORT_VIEW_PROPERTY(id, NSString) +RCT_EXPORT_VIEW_PROPERTY(existing, BOOL) +RCT_EXPORT_VIEW_PROPERTY(url, NSString) +RCT_EXPORT_VIEW_PROPERTY(shape, NSString) + +RCT_EXPORT_VIEW_PROPERTY(cluster, NSNumber) +RCT_EXPORT_VIEW_PROPERTY(clusterRadius, NSNumber) +RCT_EXPORT_VIEW_PROPERTY(clusterMaxZoomLevel, NSNumber) +RCT_EXPORT_VIEW_PROPERTY(clusterProperties, NSDictionary) +RCT_EXPORT_VIEW_PROPERTY(maxZoomLevel, NSNumber) +RCT_EXPORT_VIEW_PROPERTY(buffer, NSNumber) +RCT_EXPORT_VIEW_PROPERTY(tolerance, NSNumber) +RCT_EXPORT_VIEW_PROPERTY(lineMetrics, NSNumber) +RCT_EXPORT_VIEW_PROPERTY(images, NSDictionary) +RCT_EXPORT_VIEW_PROPERTY(nativeImages, NSArray) +RCT_EXPORT_VIEW_PROPERTY(hasPressListener, BOOL) +RCT_EXPORT_VIEW_PROPERTY(hitbox, NSDictionary) +RCT_REMAP_VIEW_PROPERTY(onMapboxShapeSourcePress, onPress, RCTBubblingEventBlock) + +@end diff --git a/ios/RNMBX/RNMBXShapeSourceManager.swift b/ios/RNMBX/RNMBXShapeSourceViewManager.swift similarity index 56% rename from ios/RNMBX/RNMBXShapeSourceManager.swift rename to ios/RNMBX/RNMBXShapeSourceViewManager.swift index a63606ed4..84f040767 100644 --- a/ios/RNMBX/RNMBXShapeSourceManager.swift +++ b/ios/RNMBX/RNMBXShapeSourceViewManager.swift @@ -1,48 +1,23 @@ -@objc(RNMBXShapeSourceManager) -class RNMBXShapeSourceManager: RCTViewManager { +@objc(RNMBXShapeSourceViewManager) +public class RNMBXShapeSourceViewManager: RCTViewManager { @objc - override static func requiresMainQueueSetup() -> Bool { + override public static func requiresMainQueueSetup() -> Bool { return true } - @objc override func view() -> UIView { + @objc override public func view() -> UIView { return RNMBXShapeSource() } } - -// MARK: - helpers - -extension RNMBXShapeSourceManager { - func withShapeSource( - _ reactTag: NSNumber, - name: String, - rejecter: @escaping RCTPromiseRejectBlock, - fn: @escaping (_: RNMBXShapeSource) -> Void) -> Void - { - self.bridge.uiManager.addUIBlock { (manager, viewRegistry) in - let view = viewRegistry![reactTag] - - guard let shapeSource = view! as? RNMBXShapeSource else { - RNMBXLogError("Invalid react tag, could not find RNMBXShapeSource"); - rejecter(name, "Unknown find reactTag: \(reactTag)", nil) - return; - } - - fn(shapeSource) - } - } -} - // MARK: - react methods -extension RNMBXShapeSourceManager { - @objc func getClusterExpansionZoom( - _ reactTag: NSNumber, +extension RNMBXShapeSourceViewManager { + @objc public static func getClusterExpansionZoom( + shapeSource: RNMBXShapeSource, featureJSON: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) -> Void { - self.withShapeSource(reactTag, name:"getCluster ExpansionZoom", rejecter: rejecter) { shapeSource in shapeSource.getClusterExpansionZoom(featureJSON) { result in switch result { case .success(let zoom): @@ -53,19 +28,17 @@ extension RNMBXShapeSourceManager { rejecter(error.localizedDescription, "Error.getClusterExpansionZoom", error) } } - } } - @objc func getClusterLeaves( - _ reactTag: NSNumber, + @objc public static func getClusterLeaves( + shapeSource: RNMBXShapeSource, featureJSON: String, number: uint, offset: uint, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) -> Void { - self.withShapeSource(reactTag, name:"getClusterLeaves", rejecter: rejecter) { shapeSource in - shapeSource.getClusterLeaves(featureJSON, number: number, offset: offset) { result in + shapeSource.getClusterLeaves(featureJSON, number: number, offset: offset) { result in switch result { case .success(let features): logged("getClusterLeaves", rejecter: rejecter) { @@ -77,16 +50,14 @@ extension RNMBXShapeSourceManager { case .failure(let error): rejecter(error.localizedDescription, "Error.getClusterLeaves", error) } - } } } - @objc func getClusterChildren( - _ reactTag: NSNumber, + @objc public static func getClusterChildren( + shapeSource: RNMBXShapeSource, featureJSON: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) -> Void { - self.withShapeSource(reactTag, name:"getClusterChildren", rejecter: rejecter) { shapeSource in shapeSource.getClusterChildren(featureJSON) { result in switch result { case .success(let features): @@ -101,6 +72,5 @@ extension RNMBXShapeSourceManager { } } } - } } diff --git a/ios/RNMBX/RNMBXSkyLayerComponentView.mm b/ios/RNMBX/RNMBXSkyLayerComponentView.mm index 923af2a04..f0e7d36f8 100644 --- a/ios/RNMBX/RNMBXSkyLayerComponentView.mm +++ b/ios/RNMBX/RNMBXSkyLayerComponentView.mm @@ -5,6 +5,7 @@ #import #import +#import #import #import @@ -34,6 +35,7 @@ - (instancetype)initWithFrame:(CGRect)frame - (void)prepareView { _view = [[RNMBXSkyLayer alloc] init]; + _view.bridge = [RCTBridge currentBridge]; self.contentView = _view; } diff --git a/ios/RNMBX/RNMBXSource.swift b/ios/RNMBX/RNMBXSource.swift index 5220f3c00..f9adcc75f 100644 --- a/ios/RNMBX/RNMBXSource.swift +++ b/ios/RNMBX/RNMBXSource.swift @@ -1,7 +1,7 @@ @_spi(Experimental) import MapboxMaps @objc -class RNMBXSource : RNMBXInteractiveElement { +public class RNMBXSource : RNMBXInteractiveElement { var layers: [RNMBXSourceConsumer] = [] var components: [RNMBXMapComponent] = [] @@ -9,7 +9,7 @@ class RNMBXSource : RNMBXInteractiveElement { var ownsSource : Bool = false - @objc var existing: Bool = false + @objc public var existing: Bool = false override func getLayerIDs() -> [String] { layers.compactMap { @@ -31,37 +31,46 @@ class RNMBXSource : RNMBXInteractiveElement { // MARK: - UIView+React - @objc override func insertReactSubview(_ subview: UIView!, at atIndex: Int) { - if let layer = subview as? RNMBXSourceConsumer { - if let map = map { - layer.addToMap(map, style: map.mapboxMap.style) - } - layers.append(layer) - } else if let component = subview as? RNMBXMapComponent { - if let map = map { - component.addToMap(map, style: map.mapboxMap.style) - } - components.append(component) - } + @objc public override func insertReactSubview(_ subview: UIView!, at atIndex: Int) { + insertReactSubviewInternal(subview, at: atIndex) super.insertReactSubview(subview, at: atIndex) } - - @objc override func removeReactSubview(_ subview: UIView!) { - if let layer : RNMBXSourceConsumer = subview as? RNMBXSourceConsumer { - if let map = map { - layer.removeFromMap(map, style: map.mapboxMap.style) - } - layers.removeAll { $0 as AnyObject === layer } - } else if let component = subview as? RNMBXMapComponent { - if let map = map { - component.removeFromMap(map, reason: .ViewRemoval) - } - layers.removeAll { $0 as AnyObject === component } + + @objc public func insertReactSubviewInternal(_ subview: UIView!, at atIndex: Int) { + if let layer = subview as? RNMBXSourceConsumer { + if let map = map { + layer.addToMap(map, style: map.mapboxMap.style) + } + layers.append(layer) + } else if let component = subview as? RNMBXMapComponent { + if let map = map { + component.addToMap(map, style: map.mapboxMap.style) + } + components.append(component) + } } + + @objc public override func removeReactSubview(_ subview: UIView!) { + removeReactSubviewInternal(subview) super.removeReactSubview(subview) } + + @objc public func removeReactSubviewInternal(_ subview: UIView!) { + if let layer : RNMBXSourceConsumer = subview as? RNMBXSourceConsumer { + if let map = map { + layer.removeFromMap(map, style: map.mapboxMap.style) + } + layers.removeAll { $0 as AnyObject === layer } + } else if let component = subview as? RNMBXMapComponent { + if let map = map { + component.removeFromMap(map, reason: .ViewRemoval) + } + layers.removeAll { $0 as AnyObject === component } + } + } + - @objc override func didUpdateReactSubviews() { + @objc public override func didUpdateReactSubviews() { // do nothing to prevent inserting layers to UIView hierarchy } diff --git a/ios/RNMBX/RNMBXSymbolLayerComponentView.mm b/ios/RNMBX/RNMBXSymbolLayerComponentView.mm index 5df7a344c..feff30f10 100644 --- a/ios/RNMBX/RNMBXSymbolLayerComponentView.mm +++ b/ios/RNMBX/RNMBXSymbolLayerComponentView.mm @@ -5,6 +5,7 @@ #import #import +#import #import #import @@ -34,6 +35,7 @@ - (instancetype)initWithFrame:(CGRect)frame - (void)prepareView { _view = [[RNMBXSymbolLayer alloc] init]; + _view.bridge = [RCTBridge currentBridge]; self.contentView = _view; } diff --git a/ios/RNMBX/RNMBXTileSource.swift b/ios/RNMBX/RNMBXTileSource.swift index bc732ea29..185b75d40 100644 --- a/ios/RNMBX/RNMBXTileSource.swift +++ b/ios/RNMBX/RNMBXTileSource.swift @@ -1,5 +1,5 @@ @objc -class RNMBXTileSource : RNMBXSource { - @objc var url: String? = nil +public class RNMBXTileSource : RNMBXSource { + @objc public var url: String? = nil } diff --git a/ios/RNMBX/RNMBXVectorSource.swift b/ios/RNMBX/RNMBXVectorSource.swift index ca4851bef..80e452bc7 100644 --- a/ios/RNMBX/RNMBXVectorSource.swift +++ b/ios/RNMBX/RNMBXVectorSource.swift @@ -1,13 +1,13 @@ import MapboxMaps @objc -class RNMBXVectorSource : RNMBXTileSource { +public class RNMBXVectorSource : RNMBXTileSource { - @objc var attribution: String? - @objc var maxZoomLevel: NSNumber? - @objc var minZoomLevel: NSNumber? - @objc var tileUrlTemplates: [String] = [] - @objc var tms: Bool = false + @objc public var attribution: String? + @objc public var maxZoomLevel: NSNumber? + @objc public var minZoomLevel: NSNumber? + @objc public var tileUrlTemplates: [String] = [] + @objc public var tms: Bool = false override func sourceType() -> Source.Type { return VectorSource.self diff --git a/ios/RNMBX/RNMBXVectorSourceComponentView.h b/ios/RNMBX/RNMBXVectorSourceComponentView.h new file mode 100644 index 000000000..bb65b4dec --- /dev/null +++ b/ios/RNMBX/RNMBXVectorSourceComponentView.h @@ -0,0 +1,17 @@ +#ifdef RCT_NEW_ARCH_ENABLED + +#import + +#import +#import + +#import "RNMBXMapFeatureView.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface RNMBXVectorSourceComponentView : RCTViewComponentView +@end + +NS_ASSUME_NONNULL_END + +#endif // RCT_NEW_ARCH_ENABLED diff --git a/ios/RNMBX/RNMBXVectorSourceComponentView.mm b/ios/RNMBX/RNMBXVectorSourceComponentView.mm new file mode 100644 index 000000000..df70fb11a --- /dev/null +++ b/ios/RNMBX/RNMBXVectorSourceComponentView.mm @@ -0,0 +1,141 @@ +#ifdef RCT_NEW_ARCH_ENABLED + +#import "RNMBXVectorSourceComponentView.h" +#import "RNMBXFabricHelpers.h" + +#import +#import + +#import +#import +#import +#import + +using namespace facebook::react; + +@interface RNMBXVectorSourceComponentView () +@end + +@implementation RNMBXVectorSourceComponentView { + RNMBXVectorSource *_view; +} + +@synthesize mapFeature; + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + [self prepareView]; + } + + return self; +} + +- (void)prepareView +{ + _view = [[RNMBXVectorSource alloc] init]; + + // capture weak self reference to prevent retain cycle + __weak __typeof__(self) weakSelf = self; + + [_view setOnPress:^(NSDictionary* event) { + __typeof__(self) strongSelf = weakSelf; + + if (strongSelf != nullptr && strongSelf->_eventEmitter != nullptr) { + const auto [type, json] = RNMBXStringifyEventData(event); + std::dynamic_pointer_cast(strongSelf->_eventEmitter)->onMapboxVectorSourcePress({type, json}); + } + }]; + + self.contentView = _view; + self.mapFeature = _view; +} + +- (void)prepareForRecycle +{ + [super prepareForRecycle]; + [self prepareView]; +} + +- (void)mountChildComponentView:(UIView *)childComponentView index:(NSInteger)index +{ + if ([childComponentView isKindOfClass:[RCTViewComponentView class]]) { + [_view insertReactSubviewInternal:((RCTViewComponentView *)childComponentView).contentView at:index]; + } else { + RCTLogError(@"Tried to add view that is not RCTViewComponentView: %@", childComponentView); + } +} + +- (void)unmountChildComponentView:(UIView *)childComponentView index:(NSInteger)index +{ + if ([childComponentView isKindOfClass:[RCTViewComponentView class]]) { + [_view removeReactSubviewInternal:((RCTViewComponentView *)childComponentView).contentView]; + } else { + RCTLogError(@"Tried to remove view that is not RCTViewComponentView: %@", childComponentView); + } +} + +#pragma mark - RCTComponentViewProtocol + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps +{ + const auto &newProps = *std::static_pointer_cast(props); + id idx = RNMBXConvertFollyDynamicToId(newProps.id); + if (idx != nil) { + _view.id = idx; + } + id existing = RNMBXConvertFollyDynamicToId(newProps.existing); + if (existing != nil) { + _view.existing = existing; + } + id url = RNMBXConvertFollyDynamicToId(newProps.url); + if (url != nil) { + _view.url = url; + } + id tileUrlTemplates = RNMBXConvertFollyDynamicToId(newProps.tileUrlTemplates); + if (tileUrlTemplates != nil) { + _view.tileUrlTemplates = tileUrlTemplates; + } + id minZoomLevel = RNMBXConvertFollyDynamicToId(newProps.minZoomLevel); + if (minZoomLevel != nil) { + _view.minZoomLevel = minZoomLevel; + } + id maxZoomLevel = RNMBXConvertFollyDynamicToId(newProps.maxZoomLevel); + if (maxZoomLevel != nil) { + _view.maxZoomLevel = maxZoomLevel; + } + id tms = RNMBXConvertFollyDynamicToId(newProps.tms); + if (tms != nil) { + _view.tms = tms; + } + id attribution = RNMBXConvertFollyDynamicToId(newProps.attribution); + if (attribution != nil) { + _view.attribution = attribution; + } + id hasPressListener = RNMBXConvertFollyDynamicToId(newProps.hasPressListener); + if (hasPressListener != nil) { + _view.hasPressListener = hasPressListener; + } + id hitbox = RNMBXConvertFollyDynamicToId(newProps.hitbox); + if (hitbox != nil) { + _view.hitbox = hitbox; + } + + [super updateProps:props oldProps:oldProps]; +} + +@end + +Class RNMBXVectorSourceCls(void) +{ + return RNMBXVectorSourceComponentView.class; +} + +#endif // RCT_NEW_ARCH_ENABLED diff --git a/ios/RNMBX/RNMBXVectorSourceManager.m b/ios/RNMBX/RNMBXVectorSourceViewManager.m similarity index 85% rename from ios/RNMBX/RNMBXVectorSourceManager.m rename to ios/RNMBX/RNMBXVectorSourceViewManager.m index 86a3d50e6..4b1ebbe9a 100644 --- a/ios/RNMBX/RNMBXVectorSourceManager.m +++ b/ios/RNMBX/RNMBXVectorSourceViewManager.m @@ -1,7 +1,7 @@ #import #import -@interface RCT_EXTERN_MODULE(RNMBXVectorSourceManager, RCTViewManager) +@interface RCT_EXTERN_REMAP_MODULE(RNMBXVectorSource, RNMBXVectorSourceViewManager, RCTViewManager) RCT_EXPORT_VIEW_PROPERTY(id, NSString) RCT_EXPORT_VIEW_PROPERTY(existing, BOOL) diff --git a/ios/RNMBX/RNMBXVectorSourceManager.swift b/ios/RNMBX/RNMBXVectorSourceViewManager.swift similarity index 65% rename from ios/RNMBX/RNMBXVectorSourceManager.swift rename to ios/RNMBX/RNMBXVectorSourceViewManager.swift index 5b8136cfc..04e897f25 100644 --- a/ios/RNMBX/RNMBXVectorSourceManager.swift +++ b/ios/RNMBX/RNMBXVectorSourceViewManager.swift @@ -1,5 +1,5 @@ -@objc(RNMBXVectorSourceManager) -class RNMBXVectorSourceManager: RCTViewManager { +@objc(RNMBXVectorSourceViewManager) +class RNMBXVectorSourceViewManager: RCTViewManager { @objc override static func requiresMainQueueSetup() -> Bool { return true diff --git a/setup-jest.js b/setup-jest.js index ed55d6eef..c95768141 100644 --- a/setup-jest.js +++ b/setup-jest.js @@ -149,6 +149,12 @@ NativeModules.RNMBXMapViewModule = { querySourceFeatures: jest.fn(), }; +NativeModules.RNMBXShapeSourceModule = { + getClusterExpansionZoom: jest.fn(), + getClusterLeaves: jest.fn(), + getClusterChildren: jest.fn(), +}; + NativeModules.RNMBXLogging = nativeModule({}); // Mock for global AbortController diff --git a/src/components/ImageSource.tsx b/src/components/ImageSource.tsx index a82e2e48c..5c842ce94 100644 --- a/src/components/ImageSource.tsx +++ b/src/components/ImageSource.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import { requireNativeComponent } from 'react-native'; import { cloneReactChildrenWithProps, @@ -7,6 +6,7 @@ import { resolveImagePath, } from '../utils'; import { BaseProps } from '../types/BaseProps'; +import RNMBXImageSourceNativeComponent from '../specs/RNMBXImageSourceNativeComponent'; import AbstractSource from './AbstractSource'; @@ -71,16 +71,14 @@ class ImageSource extends AbstractSource { }; return ( - + // @ts-expect-error just codegen stuff + {cloneReactChildrenWithProps(this.props.children, { sourceID: this.props.id, })} - + ); } } -const RNMBXImageSource = - requireNativeComponent(NATIVE_MODULE_NAME); - export default ImageSource; diff --git a/src/components/RasterDemSource.tsx b/src/components/RasterDemSource.tsx index 559e7f89d..3f978fa2d 100644 --- a/src/components/RasterDemSource.tsx +++ b/src/components/RasterDemSource.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { NativeModules, requireNativeComponent } from 'react-native'; +import { NativeModules } from 'react-native'; +import RNMBXRasterDemSourceNativeComponent from '../specs/RNMBXRasterDemSourceNativeComponent'; import { cloneReactChildrenWithProps } from '../utils'; import AbstractSource from './AbstractSource'; @@ -11,8 +12,6 @@ const isTileTemplateUrl = (url?: string): url is string => const MapboxGL = NativeModules.RNMBXModule; -export const NATIVE_MODULE_NAME = 'RNMBXRasterDemSource'; - type Props = { /** * A string that uniquely identifies the source. @@ -96,16 +95,14 @@ class RasterDemSource extends AbstractSource { tileSize: this.props.tileSize, }; return ( - + // @ts-expect-error just codegen stuff + {cloneReactChildrenWithProps(this.props.children, { sourceID: this.props.id, })} - + ); } } -const RNMBXRasterDemSource = - requireNativeComponent(NATIVE_MODULE_NAME); - export default RasterDemSource; diff --git a/src/components/RasterSource.tsx b/src/components/RasterSource.tsx index 6d6cf9da2..161180dba 100644 --- a/src/components/RasterSource.tsx +++ b/src/components/RasterSource.tsx @@ -1,15 +1,14 @@ import React from 'react'; -import { NativeModules, requireNativeComponent } from 'react-native'; +import { NativeModules } from 'react-native'; import { cloneReactChildrenWithProps } from '../utils'; import { BaseProps } from '../types/BaseProps'; +import RNMBXRasterSourceNativeComponent from '../specs/RNMBXRasterSourceNativeComponent'; import AbstractSource from './AbstractSource'; const MapboxGL = NativeModules.RNMBXModule; -export const NATIVE_MODULE_NAME = 'RNMBXRasterSource'; - const isTileTemplateUrl = (url?: string): url is string => !!url && (url.includes('{z}') || url.includes('{bbox-') || url.includes('{quadkey}')); @@ -115,16 +114,14 @@ class RasterSource extends AbstractSource { attribution: this.props.attribution, }; return ( - + // @ts-expect-error just codegen stuff + {cloneReactChildrenWithProps(this.props.children, { sourceID: this.props.id, })} - + ); } } -const RNMBXRasterSource = - requireNativeComponent(NATIVE_MODULE_NAME); - export default RasterSource; diff --git a/src/components/ShapeSource.tsx b/src/components/ShapeSource.tsx index a39fb076d..46b7d2ee1 100644 --- a/src/components/ShapeSource.tsx +++ b/src/components/ShapeSource.tsx @@ -3,10 +3,11 @@ import { NativeMethods, NativeModules, NativeSyntheticEvent, - requireNativeComponent, + findNodeHandle, } from 'react-native'; -import { getFilter } from '../utils/filterUtils'; +import RNMBXShapeSourceNativeComponent from '../specs/RNMBXShapeSourceNativeComponent'; +import NativeRNMBXShapeSourceModule from '../specs/NativeRNMBXShapeSourceModule'; import { toJSONString, cloneReactChildrenWithProps, @@ -17,7 +18,6 @@ import { copyPropertiesAsDeprecated } from '../utils/deprecation'; import { OnPressEvent } from '../types/OnPressEvent'; import AbstractSource from './AbstractSource'; -import NativeBridgeComponent from './NativeBridgeComponent'; const MapboxGL = NativeModules.RNMBXModule; @@ -148,10 +148,7 @@ export type Props = { * ShapeSource is a map content source that supplies vector shapes to be shown on the map. * The shape may be an url or a GeoJSON object */ -export class ShapeSource extends NativeBridgeComponent( - AbstractSource, - NATIVE_MODULE_NAME, -) { +export class ShapeSource extends AbstractSource { static NATIVE_ASSETS_KEY = 'assets'; static defaultProps = { @@ -166,31 +163,6 @@ export class ShapeSource extends NativeBridgeComponent( nativeRef: React.Component & Readonly, ) { this.setNativeRef(nativeRef); - super._runPendingNativeCommands(nativeRef); - } - - /** - * Returns all features from the source that match the query parameters whether the feature is currently - * rendered on the map. - * - * @example - * shapeSource.features() - * - * @param {Array=} filter - an optional filter statement to filter the returned Features. - * @return {FeatureCollection} - */ - async features(filter: Array = []) { - const res: { data: string } = await this._runNativeCommand( - 'features', - this._nativeRef, - getFilter(filter), - ); - - if (isAndroid()) { - return JSON.parse(res.data); - } - - return res.data; } /** @@ -209,19 +181,14 @@ export class ShapeSource extends NativeBridgeComponent( console.warn( 'Using cluster_id is deprecated and will be removed from the future releases. Please use cluster as an argument instead.', ); - const res: { data: number } = await this._runNativeCommand( - 'getClusterExpansionZoomById', - this._nativeRef, - [feature], - ); - return res.data; } - const res: { data: number } = await this._runNativeCommand( - 'getClusterExpansionZoom', - this._nativeRef, - [JSON.stringify(feature)], - ); + const handle = findNodeHandle(this._nativeRef as any); + + const res = (await NativeRNMBXShapeSourceModule.getClusterExpansionZoom( + handle, + JSON.stringify(feature), + )) as { data: number }; return res.data; } @@ -245,24 +212,16 @@ export class ShapeSource extends NativeBridgeComponent( console.warn( 'Using cluster_id is deprecated and will be removed from the future releases. Please use cluster as an argument instead.', ); - const res: { data: string } = await this._runNativeCommand( - 'getClusterLeavesById', - this._nativeRef, - [feature, limit, offset], - ); - - if (isAndroid()) { - return JSON.parse(res.data); - } - - return res.data; } - const res: { data: string } = await this._runNativeCommand( - 'getClusterLeaves', - this._nativeRef, - [JSON.stringify(feature), limit, offset], - ); + const handle = findNodeHandle(this._nativeRef as any); + + const res = (await NativeRNMBXShapeSourceModule.getClusterLeaves( + handle, + JSON.stringify(feature), + limit, + offset, + )) as { data: string }; if (isAndroid()) { return JSON.parse(res.data); @@ -285,24 +244,14 @@ export class ShapeSource extends NativeBridgeComponent( console.warn( 'Using cluster_id is deprecated and will be removed from the future releases. Please use cluster as an argument instead.', ); - const res: { data: string } = await this._runNativeCommand( - 'getClusterChildrenById', - this._nativeRef, - [feature], - ); - - if (isAndroid()) { - return JSON.parse(res.data); - } - - return res.data; } - const res: { data: string } = await this._runNativeCommand( - 'getClusterChildren', - this._nativeRef, - [JSON.stringify(feature)], - ); + const handle = findNodeHandle(this._nativeRef as any); + + const res = (await NativeRNMBXShapeSourceModule.getClusterChildren( + handle, + JSON.stringify(feature), + )) as { data: string }; if (isAndroid()) { return JSON.parse(res.data); @@ -329,16 +278,23 @@ export class ShapeSource extends NativeBridgeComponent( return toJSONString(this.props.shape); } + _decodePayload(payload: OnPressEvent | string): OnPressEvent { + // we check whether the payload is a string, since the strict type safety is enforced only on iOS on the new arch + // on Android, on both archs, the payload is an object + if (typeof payload === 'string') { + return JSON.parse(payload); + } else { + return payload; + } + } + onPress( event: NativeSyntheticEvent<{ payload: OnPressEvent; }>, ) { - const { - nativeEvent: { - payload: { features, coordinates, point }, - }, - } = event; + const payload = this._decodePayload(event.nativeEvent.payload); + const { features, coordinates, point } = payload; let newEvent: OnPressEventDeprecated = { features, coordinates, @@ -384,15 +340,15 @@ export class ShapeSource extends NativeBridgeComponent( ref: ( nativeRef: React.Component & Readonly, ) => this._setNativeRef(nativeRef), - onAndroidCallback: isAndroid() ? this._onAndroidCallback : undefined, }; return ( - + // @ts-expect-error just codegen stuff + {cloneReactChildrenWithProps(this.props.children, { sourceID: this.props.id, })} - + ); } } @@ -401,6 +357,3 @@ type NativeProps = { id: string; shape?: string; }; - -const RNMBXShapeSource = - requireNativeComponent(NATIVE_MODULE_NAME); diff --git a/src/components/VectorSource.tsx b/src/components/VectorSource.tsx index 97f988827..722e6d994 100644 --- a/src/components/VectorSource.tsx +++ b/src/components/VectorSource.tsx @@ -3,16 +3,14 @@ import { NativeMethods, NativeModules, NativeSyntheticEvent, - requireNativeComponent, } from 'react-native'; -import { cloneReactChildrenWithProps, isFunction, isAndroid } from '../utils'; -import { getFilter } from '../utils/filterUtils'; +import RNMBXVectorSourceNativeComponent from '../specs/RNMBXVectorSourceNativeComponent'; +import { cloneReactChildrenWithProps, isFunction } from '../utils'; import { copyPropertiesAsDeprecated } from '../utils/deprecation'; import { OnPressEvent } from '../types/OnPressEvent'; import AbstractSource from './AbstractSource'; -import NativeBridgeComponent from './NativeBridgeComponent'; const MapboxGL = NativeModules.RNMBXModule; @@ -99,10 +97,7 @@ type NativeProps = Props; // Omit; * VectorSource is a map content source that supplies tiled vector data in Mapbox Vector Tile format to be shown on the map. * The location of and metadata about the tiles are defined either by an option dictionary or by an external file that conforms to the TileJSON specification. */ -class VectorSource extends NativeBridgeComponent( - AbstractSource, - NATIVE_MODULE_NAME, -) { +class VectorSource extends AbstractSource { static defaultProps = { id: MapboxGL.StyleSource.DefaultSourceID, }; @@ -117,46 +112,26 @@ class VectorSource extends NativeBridgeComponent( if (nativeRef) { this.setNativeRef(nativeRef); // this._nativeRef = nativeRef; - super._runPendingNativeCommands(nativeRef); } } - /** - * Returns all features that match the query parameters regardless of whether or not the feature is - * currently rendered on the map. The domain of the query includes all currently-loaded vector tiles - * and GeoJSON source tiles. This function does not check tiles outside of the visible viewport. - * - * @example - * vectorSource.features(['id1', 'id2']) - * - * @param {Array=} layerIDs - A set of strings that correspond to the names of layers defined in the current style. Only the features contained in these layers are included in the returned array. - * @param {Array=} filter - an optional filter statement to filter the returned Features. - * @return {FeatureCollection} - */ - async features(layerIDs = [], filter = []) { - const res: { data: string } = await this._runNativeCommand( - 'features', - this._nativeRef, - [layerIDs, getFilter(filter)], - ); - - if (isAndroid()) { - return JSON.parse(res.data); + _decodePayload(payload: OnPressEvent | string): OnPressEvent { + // we check whether the payload is a string, since the strict type safety is enforced only on iOS on the new arch + // on Android, on both archs, the payload is an object + if (typeof payload === 'string') { + return JSON.parse(payload); + } else { + return payload; } - - return res.data; } onPress( event: NativeSyntheticEvent<{ - payload: OnPressEvent; + payload: OnPressEvent | string; }>, ) { - const { - nativeEvent: { - payload: { features, coordinates, point }, - }, - } = event; + const payload = this._decodePayload(event.nativeEvent.payload); + const { features, coordinates, point } = payload; let newEvent = { features, coordinates, @@ -197,19 +172,20 @@ class VectorSource extends NativeBridgeComponent( hasPressListener: isFunction(this.props.onPress), onMapboxVectorSourcePress: this.onPress.bind(this), onPress: undefined, - onAndroidCallback: isAndroid() ? this._onAndroidCallback : undefined, }; return ( - this._setNativeRef(r)} {...props}> + // @ts-expect-error just codegen stuff + this._setNativeRef(r)} + {...props} + > {cloneReactChildrenWithProps(this.props.children, { sourceID: this.props.id, })} - + ); } } -const RNMBXVectorSource = - requireNativeComponent(NATIVE_MODULE_NAME); - export default VectorSource; diff --git a/src/specs/NativeRNMBXShapeSourceModule.ts b/src/specs/NativeRNMBXShapeSourceModule.ts new file mode 100644 index 000000000..3a8b15809 --- /dev/null +++ b/src/specs/NativeRNMBXShapeSourceModule.ts @@ -0,0 +1,23 @@ +/* eslint-disable @typescript-eslint/ban-types */ +import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport'; +import { Int32 } from 'react-native/Libraries/Types/CodegenTypes'; +import { TurboModuleRegistry } from 'react-native'; + +export interface Spec extends TurboModule { + getClusterExpansionZoom: ( + viewRef: Int32 | null, + featureJSON: string, + ) => Promise; + getClusterLeaves: ( + viewRef: Int32 | null, + featureJSON: string, + number: Int32, + offset: Int32, + ) => Promise; + getClusterChildren: ( + viewRef: Int32 | null, + featureJSON: string, + ) => Promise; +} + +export default TurboModuleRegistry.getEnforcing('RNMBXShapeSourceModule'); diff --git a/src/specs/RNMBXImageSourceNativeComponent.ts b/src/specs/RNMBXImageSourceNativeComponent.ts new file mode 100644 index 000000000..8b053b092 --- /dev/null +++ b/src/specs/RNMBXImageSourceNativeComponent.ts @@ -0,0 +1,15 @@ +import type { HostComponent, ViewProps } from 'react-native'; +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; + +import { UnsafeMixed } from './codegenUtils'; + +export interface NativeProps extends ViewProps { + id: UnsafeMixed; + existing: UnsafeMixed; + url: UnsafeMixed; + coordinates: UnsafeMixed; +} + +export default codegenNativeComponent( + 'RNMBXImageSource', +) as HostComponent; diff --git a/src/specs/RNMBXRasterDemSourceNativeComponent.ts b/src/specs/RNMBXRasterDemSourceNativeComponent.ts new file mode 100644 index 000000000..521a5ccc2 --- /dev/null +++ b/src/specs/RNMBXRasterDemSourceNativeComponent.ts @@ -0,0 +1,19 @@ +import type { HostComponent, ViewProps } from 'react-native'; +import { Double } from 'react-native/Libraries/Types/CodegenTypes'; +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; + +import { UnsafeMixed } from './codegenUtils'; + +export interface NativeProps extends ViewProps { + id: UnsafeMixed; + existing: UnsafeMixed; + url: UnsafeMixed; + tileUrlTemplates: UnsafeMixed>; + minZoomLevel: UnsafeMixed; + maxZoomLevel: UnsafeMixed; + tileSize: UnsafeMixed; +} + +export default codegenNativeComponent( + 'RNMBXRasterDemSource', +) as HostComponent; diff --git a/src/specs/RNMBXRasterSourceNativeComponent.ts b/src/specs/RNMBXRasterSourceNativeComponent.ts new file mode 100644 index 000000000..5b55eaad6 --- /dev/null +++ b/src/specs/RNMBXRasterSourceNativeComponent.ts @@ -0,0 +1,21 @@ +import type { HostComponent, ViewProps } from 'react-native'; +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; +import { Double } from 'react-native/Libraries/Types/CodegenTypes'; + +import { UnsafeMixed } from './codegenUtils'; + +export interface NativeProps extends ViewProps { + id: UnsafeMixed; + existing: UnsafeMixed; + url: UnsafeMixed; + tileUrlTemplates: UnsafeMixed>; + minZoomLevel: UnsafeMixed; + maxZoomLevel: UnsafeMixed; + tileSize: UnsafeMixed; + tms: UnsafeMixed; + attribution: UnsafeMixed; +} + +export default codegenNativeComponent( + 'RNMBXRasterSource', +) as HostComponent; diff --git a/src/specs/RNMBXShapeSourceNativeComponent.ts b/src/specs/RNMBXShapeSourceNativeComponent.ts new file mode 100644 index 000000000..39c9090e0 --- /dev/null +++ b/src/specs/RNMBXShapeSourceNativeComponent.ts @@ -0,0 +1,35 @@ +import type { HostComponent, ViewProps } from 'react-native'; +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; +import { + DirectEventHandler, + Double, + Int32, +} from 'react-native/Libraries/Types/CodegenTypes'; + +import type { UnsafeMixed } from './codegenUtils'; + +type OnMapboxShapeSourcePressEventType = { type: string; payload: string }; + +export interface NativeProps extends ViewProps { + id: UnsafeMixed; + existing: UnsafeMixed; + url: UnsafeMixed; + shape: UnsafeMixed; + cluster: UnsafeMixed; + clusterRadius: UnsafeMixed; + clusterMaxZoomLevel: UnsafeMixed; + clusterProperties: UnsafeMixed; + maxZoomLevel: UnsafeMixed; + buffer: UnsafeMixed; + tolerance: UnsafeMixed; + lineMetrics: UnsafeMixed; + images: UnsafeMixed; // unused ?? + nativeImages: UnsafeMixed>; // unused ?? + hasPressListener: UnsafeMixed; + hitbox: UnsafeMixed; + onMapboxShapeSourcePress: DirectEventHandler; +} + +export default codegenNativeComponent( + 'RNMBXShapeSource', +) as HostComponent; diff --git a/src/specs/RNMBXVectorSourceNativeComponent.ts b/src/specs/RNMBXVectorSourceNativeComponent.ts new file mode 100644 index 000000000..aad3b26f2 --- /dev/null +++ b/src/specs/RNMBXVectorSourceNativeComponent.ts @@ -0,0 +1,28 @@ +import type { HostComponent, ViewProps } from 'react-native'; +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; +import { + DirectEventHandler, + Double, +} from 'react-native/Libraries/Types/CodegenTypes'; + +import type { UnsafeMixed } from './codegenUtils'; + +type OnMapboxVectorSourcePressEventType = { type: string; payload: string }; + +export interface NativeProps extends ViewProps { + id: UnsafeMixed; + existing: UnsafeMixed; + url: UnsafeMixed; + tileUrlTemplates: UnsafeMixed>; + attribution: UnsafeMixed; + maxZoomLevel: UnsafeMixed; + minZoomLevel: UnsafeMixed; + tms: UnsafeMixed; + hasPressListener: UnsafeMixed; + hitbox: UnsafeMixed; + onMapboxVectorSourcePress: DirectEventHandler; +} + +export default codegenNativeComponent( + 'RNMBXVectorSource', +) as HostComponent;