Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: migrate RNMBXSources to new arch #3123

Merged
merged 9 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions android/src/main/java/com/rnmapbox/rnmbx/RNMBXPackage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -190,7 +190,7 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie
*/
public var offscreenAnnotationViewContainer: ViewGroup? = null

private val mSources: MutableMap<String, RCTSource<*>>
private val mSources: MutableMap<String, RNMBXSource<*>>
private val mImages: MutableList<RNMBXImages>
private var mPointAnnotationManager: PointAnnotationManager? = null
private var mActiveMarkerID: AnnotationID = INVALID_ANNOTATION_ID
Expand Down Expand Up @@ -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?
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -553,9 +553,9 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie
}


private val allTouchableSources: List<RCTSource<*>>
private val allTouchableSources: List<RNMBXSource<*>>
private get() {
val sources: MutableList<RCTSource<*>> = ArrayList()
val sources: MutableList<RNMBXSource<*>> = ArrayList()
for (key in mSources.keys) {
val source = mSources[key]
if (source != null && source.hasPressListener()) {
Expand All @@ -565,14 +565,14 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie
return sources
}

private fun getTouchableSourceWithHighestZIndex(sources: List<RCTSource<*>>?): RCTSource<*>? {
private fun getTouchableSourceWithHighestZIndex(sources: List<RNMBXSource<*>>?): RNMBXSource<*>? {
if (sources == null || sources.size == 0) {
return null
}
if (sources.size == 1) {
return sources[0]
}
val layerToSourceMap: MutableMap<String, RCTSource<*>> = HashMap()
val layerToSourceMap: MutableMap<String, RNMBXSource<*>> = HashMap()
for (source in sources) {
val layerIDs: Array<out String>? = source.layerIDs.toTypedArray()
if (layerIDs != null) {
Expand Down Expand Up @@ -662,13 +662,13 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie
}

interface HandleTap {
fun run(hitTouchableSources: List<RCTSource<*>?>?, hits: Map<String?, List<Feature?>?>)
fun run(hitTouchableSources: List<RNMBXSource<*>?>?, hits: Map<String?, List<Feature?>?>)
}

fun handleTapInSources(
sources: LinkedList<RCTSource<*>>, screenPoint: ScreenCoordinate,
sources: LinkedList<RNMBXSource<*>>, screenPoint: ScreenCoordinate,
hits: HashMap<String?, List<Feature?>?>,
hitTouchableSources: ArrayList<RCTSource<*>?>,
hitTouchableSources: ArrayList<RNMBXSource<*>?>,
handleTap: HandleTap
) {
if (sources.isEmpty()) {
Expand Down Expand Up @@ -723,11 +723,11 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie
val hits = HashMap<String?, List<Feature?>?>()
if (screenPoint != null) {
handleTapInSources(LinkedList(touchableSources), screenPoint, hits, ArrayList(), object : HandleTap {
override fun run(hitTouchableSources: List<RCTSource<*>?>?, hits: Map<String?, List<Feature?>?>) {
override fun run(hitTouchableSources: List<RNMBXSource<*>?>?, hits: Map<String?, List<Feature?>?>) {
if (hits.size > 0) {
val source = getTouchableSourceWithHighestZIndex(hitTouchableSources as List<RCTSource<*>>?)
val source = getTouchableSourceWithHighestZIndex(hitTouchableSources as List<RNMBXSource<*>>?)
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<Feature>,
GeoJSONUtils.toLatLng(point),
PointF(screenPoint.x.toFloat(), screenPoint.y.toFloat())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<ImageSource?>(context) {
class RNMBXImageSource(context: Context?) : RNMBXSource<ImageSource?>(context) {
private var mURL: URL? = null
private var mResourceId = 0
private var mCoordQuad: LatLngQuad? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -23,7 +24,7 @@ import java.util.HashMap
import com.rnmapbox.rnmbx.v11compat.feature.*

class RNMBXShapeSource(context: Context, private val mManager: RNMBXShapeSourceManager) :
RCTSource<GeoJsonSource>(context) {
RNMBXSource<GeoJsonSource>(context) {
private var mURL: URL? = null
private var mShape: String? = null
private var mCluster: Boolean? = null
Expand Down Expand Up @@ -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 ->
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -153,52 +151,8 @@ class RNMBXShapeSourceManager(private val mContext: ReactApplicationContext) :
.build()
}

override fun getCommandsMap(): Map<String, Int>? {
return MapBuilder.builder<String, Int>()
.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
}
}
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
Loading