Skip to content

Commit

Permalink
feat: mapViewImpl so native code can register custom mapView factory (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
mfazekas authored Dec 15, 2023
1 parent bad4488 commit 5bd099b
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,22 @@ data class FeatureEntry(val feature: AbstractMapFeature?, val view: View?, var a

}

typealias Factory = (impl: String, ViewGroup) -> MapView?;
public class RNMBXMapViewFactory {
companion object {
var factories = mutableMapOf<String,Factory>();
fun regiser(impl: String, factory: Factory) {
val (impl, options) = impl.split(":",limit=2)
factories.put(impl, factory);
}

fun get(impl: String): Factory? {
val (impl, options) = impl.split(":",limit=2);
return factories.get(impl);
}
}
}

open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapViewManager, options: MapInitOptions?) : FrameLayout(mContext), OnMapClickListener, OnMapLongClickListener, OnLayoutChangeListener {
/**
* `PointAnnotations` are rendered to a canvas, but the React Native `Image` component is
Expand Down Expand Up @@ -249,6 +265,8 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie
private var wasGestureActive = false
private var isGestureActive = false

var mapViewImpl: String? = null

val mapView: MapView
get() = this.mMapView

Expand Down Expand Up @@ -1136,17 +1154,37 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie
const val LOG_TAG = "RNMBXMapView"
}

fun createAndAddMapView(mapViewImpl: String): MapView? {
RNMBXMapViewFactory.get(mapViewImpl)?.let {
return it(mapViewImpl, this);
}
return null;
}

fun createMapView() : MapView {
var options: MapInitOptions? = null
if (surfaceView == false) {
options = MapInitOptions(context= mContext, textureView= true)
var created = false;
mapViewImpl?.also {impl ->
createAndAddMapView(impl)?.let { mapView ->
mMapView = mapView
created = true;
}
}
val mapView = if (options != null) MapView(mContext, options) else MapView(mContext)
mMapView = mapView
if (!created) {
var options: MapInitOptions? = null
if (surfaceView == false) {
options = MapInitOptions(context = mContext, textureView = true)
}
val mapView = if (options != null) MapView(mContext, options) else MapView(mContext)
mMapView = mapView


val matchParent = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
mapView.setLayoutParams(matchParent)
addView(mapView)
val matchParent = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
mapView.setLayoutParams(matchParent)
addView(mapView)
}
this.addOnLayoutChangeListener(this)

val map = mapView.getMapboxMap()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,13 @@ open class RNMBXMapViewManager(context: ReactApplicationContext, val viewTagReso
}
}

@ReactProp(name = "mapViewImpl")
override fun setMapViewImpl(mapView: RNMBXMapView, value: Dynamic?) {
value?.let {
mapView.mapViewImpl = it.asString()
}
}

override fun setCompassImage(view: RNMBXMapView, value: Dynamic?) {
// TODO: No-op on Android?
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "compassImage":
mViewManager.setCompassImage(view, new DynamicFromObject(value));
break;
case "mapViewImpl":
mViewManager.setMapViewImpl(view, new DynamicFromObject(value));
break;
default:
super.setProperty(view, propName, value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ public interface RNMBXMapViewManagerInterface<T extends View> {
void setAttributionViewMargins(T view, Dynamic value);
void setAttributionViewPosition(T view, Dynamic value);
void setCompassImage(T view, Dynamic value);
void setMapViewImpl(T view, Dynamic value);
}
54 changes: 45 additions & 9 deletions ios/RNMBX/RNMBXMapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@
import Turf
import MapKit

public typealias RNMBXMapViewFactoryFunc = (String, UIView) -> MapView?;

/**
* Experimental MapView factory for advanced usecases
*/
public class RNMBXMapViewFactory {
private static var factories: [String: RNMBXMapViewFactoryFunc] = [:];

static func get(_ id: String) -> RNMBXMapViewFactoryFunc? {
if let id = id.split(separator: ":", maxSplits: 1).first {
return factories[String(id)]
}
return nil
}

public static func register(_ id: String, factory: @escaping RNMBXMapViewFactoryFunc) {
factories.updateValue(factory, forKey: id)
}
}

class FeatureEntry {
let feature: RNMBXMapComponent
let view: UIView
Expand Down Expand Up @@ -132,6 +152,9 @@ open class RNMBXMapView: UIView {

@objc
public var deselectAnnotationOnTap: Bool = false

@objc
public var mapViewImpl : String? = nil

#if RNMBX_11
var cancelables = Set<AnyCancelable>()
Expand All @@ -149,19 +172,32 @@ open class RNMBXMapView: UIView {

var _mapView: MapView! = nil
func createMapView() {
#if RNMBX_11
_mapView = MapView(frame: self.bounds, mapInitOptions: MapInitOptions())
#else
let resourceOptions = ResourceOptions(accessToken: RNMBXModule.accessToken!)
_mapView = MapView(frame: frame, mapInitOptions: MapInitOptions(resourceOptions: resourceOptions))
#endif
_mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
addSubview(_mapView)
if let mapViewImpl = mapViewImpl, let mapViewInstance = createAndAddMapViewImpl(mapViewImpl, self) {
_mapView = mapViewInstance
} else {
#if RNMBX_11
_mapView = MapView(frame: self.bounds, mapInitOptions: MapInitOptions())
#else
let resourceOptions = ResourceOptions(accessToken: RNMBXModule.accessToken!)
_mapView = MapView(frame: frame, mapInitOptions: MapInitOptions(resourceOptions: resourceOptions))
#endif
_mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
addSubview(_mapView)
}

_mapView.gestures.delegate = self
setupEvents()
}


func createAndAddMapViewImpl(_ impl: String, _ view: RNMBXMapView) -> MapView? {
if let factory = RNMBXMapViewFactory.get(impl) {
return factory(impl, view) as? MapView;
} else {
Logger.log(level:.error, message: "No mapview factory registered for: \(impl)")
return nil
}
}

var mapView : MapView! {
get { return _mapView }
}
Expand Down
8 changes: 7 additions & 1 deletion scripts/autogenHelpers/DocJSONBuilder.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,18 @@ class DocJSONBuilder {
}

postprocess(component, name) {
// Remove all private methods and parse examples from docblock
// Remove all private methods, and properties and parse examples from docblock

if (!Array.isArray(component.methods)) {
return;
}

for (const [propName, prop] of Object.entries(component.props)) {
if (prop.description.includes('@private')) {
delete component.props[propName];
}
}

component.name = name;

// Main description
Expand Down
5 changes: 5 additions & 0 deletions src/components/MapView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,11 @@ type Props = ViewProps & {
* the onPress event for the taps that deselect the annotation. Default is false.
*/
deselectAnnotationOnTap?: boolean;

/**
* @private Experimental support for custom MapView instances
*/
mapViewImpl?: string;
};

type CallbablePropKeys =
Expand Down
2 changes: 2 additions & 0 deletions src/specs/RNMBXMapViewNativeComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ export interface NativeProps extends ViewProps {
onLongPress?: DirectEventHandler<OnPressEventType>;
onMapChange?: DirectEventHandler<OnMapChangeEventType>;
onCameraChanged?: DirectEventHandler<OnCameraChangedEventType>;

mapViewImpl?: OptionalProp<string>;
}

export default codegenNativeComponent<NativeProps>(
Expand Down

0 comments on commit 5bd099b

Please sign in to comment.