From 9619111a9aa30737e23b4eef55c66527c4f6273c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 26 Oct 2023 12:27:48 +0200 Subject: [PATCH 1/4] refactor: remove RNMBPXAndroidTextureMapView, and lateinit MapView on android --- .../java/com/rnmapbox/rnmbx/RNMBXPackage.kt | 2 - .../RNMBXAndroidTextureMapViewManager.kt | 39 ---- .../rnmbx/components/mapview/RNMBXMapView.kt | 188 ++++++++++++------ .../components/mapview/RNMBXMapViewManager.kt | 126 +++++++----- .../rnmapbox/rnmbx/utils/PropertyChanges.kt | 68 +++++++ ...XAndroidTextureMapViewManagerDelegate.java | 95 --------- ...AndroidTextureMapViewManagerInterface.java | 38 ---- .../RNMBXMapViewManagerDelegate.java | 3 + .../RNMBXMapViewManagerInterface.java | 1 + src/components/MapView.tsx | 43 ++-- ...MBXAndroidTextureMapViewNativeComponent.ts | 59 ------ src/specs/RNMBXMapViewNativeComponent.ts | 38 +++- src/specs/codegenUtils.ts | 5 - 13 files changed, 322 insertions(+), 383 deletions(-) delete mode 100644 android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXAndroidTextureMapViewManager.kt create mode 100644 android/src/main/java/com/rnmapbox/rnmbx/utils/PropertyChanges.kt delete mode 100644 android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXAndroidTextureMapViewManagerDelegate.java delete mode 100644 android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXAndroidTextureMapViewManagerInterface.java delete mode 100644 src/specs/RNMBXAndroidTextureMapViewNativeComponent.ts diff --git a/android/src/main/java/com/rnmapbox/rnmbx/RNMBXPackage.kt b/android/src/main/java/com/rnmapbox/rnmbx/RNMBXPackage.kt index 84d8e3ac9..25842d2a3 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/RNMBXPackage.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/RNMBXPackage.kt @@ -17,7 +17,6 @@ import com.rnmapbox.rnmbx.components.images.RNMBXImageModule import com.rnmapbox.rnmbx.components.images.RNMBXImagesManager import com.rnmapbox.rnmbx.components.location.RNMBXNativeUserLocationManager import com.rnmapbox.rnmbx.components.mapview.NativeMapViewModule -import com.rnmapbox.rnmbx.components.mapview.RNMBXAndroidTextureMapViewManager import com.rnmapbox.rnmbx.components.mapview.RNMBXMapViewManager import com.rnmapbox.rnmbx.components.styles.RNMBXStyleImportManager import com.rnmapbox.rnmbx.components.styles.atmosphere.RNMBXAtmosphereManager @@ -86,7 +85,6 @@ class RNMBXPackage : TurboReactPackage() { // components managers.add(RNMBXCameraManager(reactApplicationContext)) - managers.add(RNMBXAndroidTextureMapViewManager(reactApplicationContext, getViewTagResolver(reactApplicationContext))) managers.add(RNMBXMapViewManager(reactApplicationContext, getViewTagResolver(reactApplicationContext))) managers.add(RNMBXStyleImportManager(reactApplicationContext)) diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXAndroidTextureMapViewManager.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXAndroidTextureMapViewManager.kt deleted file mode 100644 index 8ac8b105f..000000000 --- a/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXAndroidTextureMapViewManager.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.rnmapbox.rnmbx.components.mapview - -import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.uimanager.ThemedReactContext -import com.facebook.react.uimanager.ViewManagerDelegate -import com.facebook.react.viewmanagers.RNMBXAndroidTextureMapViewManagerDelegate -import com.facebook.react.viewmanagers.RNMBXAndroidTextureMapViewManagerInterface -import com.facebook.react.viewmanagers.RNMBXMapViewManagerDelegate -import com.mapbox.maps.MapInitOptions -import com.rnmapbox.rnmbx.utils.ViewTagResolver - -class RNMBXAndroidTextureMapViewManager(context: ReactApplicationContext, viewTagResolver: ViewTagResolver) : RNMBXMapViewManager( - context, - viewTagResolver -), RNMBXAndroidTextureMapViewManagerInterface { - private val mDelegate: ViewManagerDelegate - - init { - mDelegate = RNMBXAndroidTextureMapViewManagerDelegate(this) - } - - override fun getDelegate(): ViewManagerDelegate? { - return mDelegate - } - - override fun getName(): String { - return REACT_CLASS - } - - override fun createViewInstance(themedReactContext: ThemedReactContext): RNMBXMapView { - val context = getMapViewContext(themedReactContext) - val options = MapInitOptions(context = context, textureView= true) - return RNMBXMapView(context, this, options) - } - - companion object { - const val REACT_CLASS = "RNMBXAndroidTextureMapView" - } -} \ No newline at end of file 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 d67ffd546..1a99e2e27 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 @@ -217,9 +217,11 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie private var mQueuedFeatures: MutableList? = ArrayList() private val mPointAnnotations: MutableMap private val mCameraChangeTracker = CameraChangeTracker() - private val mMap: MapboxMap? + private lateinit var mMap: MapboxMap - private val mMapView: MapView + private lateinit var mMapView: MapView + val isInitialized: Boolean + get() = this::mMapView.isInitialized var savedStyle: Style? = null private set @@ -327,8 +329,8 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie style.setProjection(Projection(mProjection)) } - private fun setupEvents() { - mMap?.addOnRenderFrameFinishedListener( + private fun setupEvents(map: MapboxMap) { + map.addOnRenderFrameFinishedListener( object: OnRenderFrameFinishedListener { override fun onRenderFrameFinished(eventData: RenderFrameFinishedEventData) { handleMapChangedEvent(EventTypes.DID_FINISH_RENDERING_FRAME_FULLY) @@ -485,10 +487,10 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie feature = childView as AbstractMapFeature } else if (childView is ViewGroup) { val children = childView - Logger.w(LOG_TAG, "Adding non map components as a child of a map is deprecated!") - for (i in 0 until children.childCount) { - addView(children.getChildAt(i), childPosition) - } + Logger.w(LOG_TAG, "Adding non map components:${children.javaClass.name} as a child of a map is deprecated!") + //for (i in 0 until children.childCount) { + // addView(children.getChildAt(i), childPosition) + //} } val addToMap = styleLoaded || (feature?.requiresStyleLoad == false) @@ -619,13 +621,60 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie return true } + // region properties + var surfaceView: Boolean? = null + + enum class Property(val _apply: (RNMBXMapView) -> Unit) : PropertyUpdaterWithName { + PROJECTION(RNMBXMapView::applyProjection), + LOCALIZE_LABELS(RNMBXMapView::applyLocalizeLabels), + STYLE_URL(RNMBXMapView::applyStyleURL), + ATTRIBUTION(RNMBXMapView::applyAttribution), + LOGO(RNMBXMapView::applyLogo), + SCALEBAR(RNMBXMapView::applyScaleBar), + COMPASS(RNMBXMapView::applyCompass),; + + override fun apply(mapView: RNMBXMapView) { + _apply(mapView) + } + } + + val changes = PropertyChanges(); + + var withMapWaiters = mutableListOf<(map: MapView)->Unit>(); + fun withMap(callback: (map: MapboxMap) -> Unit) { + if (! this::mMap.isInitialized) { + withMapWaiters.add { it -> callback(it.getMapboxMap()) } + } else { + callback(mMap) + } + } + fun withMapView(callback: (map: MapView) -> Unit) { + if (! this::mMapView.isInitialized) { + withMapWaiters.add(callback) + } else { + callback(mMapView) + } + } + fun applyAllChanges() { + if (! this::mMapView.isInitialized) { + createMapView() + withMapWaiters.forEach { it(mMapView) } + withMapWaiters.clear() + } + changes.apply(this) + } + + fun setReactProjection(projection: ProjectionName) { if (projection != null) { mProjection = projection } + changes.add(Property.PROJECTION) + } + fun applyProjection() { if (mMap != null) { - mMap.getStyle()?.setProjection(Projection(projection)) + mMap.getStyle()?.setProjection(Projection(mProjection)) } } @@ -642,14 +691,18 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie mLocaleString = localeStr mLocaleLayerIds = layerIds } - applyLocalizeLabels() + changes.add(Property.LOCALIZE_LABELS) } fun setReactStyleURL(styleURL: String) { mStyleURL = styleURL - if (mMap != null) { + changes.add(Property.STYLE_URL) + } + fun applyStyleURL() { + val styleURL = mStyleURL + if (mMap != null && styleURL != null) { removeAllFeatureFromMap(RemovalReason.STYLE_CHANGE) - if (isJSONValid(mStyleURL)) { + if (isJSONValid(styleURL)) { styleLoaded = false mMap.loadStyleJson(styleURL, object : Style.OnStyleLoaded { override fun onStyleLoaded(style: Style) { @@ -663,16 +716,17 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie styleLoaded(style) } }, - object : OnMapLoadErrorListener { - override fun onMapLoadError(mapLoadingErrorEventData: MapLoadingErrorEventData) { - Logger.w("MapLoadError", mapLoadingErrorEventData.message) - } + object : OnMapLoadErrorListener { + override fun onMapLoadError(mapLoadingErrorEventData: MapLoadingErrorEventData) { + Logger.w("MapLoadError", mapLoadingErrorEventData.message) } + } ) addFeaturesToMap(false) } } } + //endregion interface HandleTap { fun run(hitTouchableSources: List?>?, hits: Map?>) @@ -947,7 +1001,7 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie // } //} - // region Callbacks + // region Methods fun getCenter(response: CommandResponse) { var center = mMap!!.cameraState!!.center @@ -1154,51 +1208,61 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie } } } - // endregion companion object { const val LOG_TAG = "RNMBXMapView" } - init { - offscreenAnnotationViewContainer = FrameLayout(getContext()) - val p = FrameLayout.LayoutParams(0, 0) - p.setMargins(-10000, -10000, -10000, -10000) - offscreenAnnotationViewContainer?.setLayoutParams(p) - addView(offscreenAnnotationViewContainer) - - mMapView = if (options != null) MapView(mContext, options) else MapView(mContext) + fun createMapView() : MapView { + 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) - mMapView.setLayoutParams(matchParent) - addView(mMapView) - - mMap = mapView.getMapboxMap() - mSources = HashMap() - mImages = ArrayList() - mPointAnnotations = HashMap() + mapView.setLayoutParams(matchParent) + addView(mapView) + this.addOnLayoutChangeListener(this) - onMapReady(mMap) + val map = mapView.getMapboxMap() + mMap = map val _this = this - mMap.addOnMapLoadedListener(OnMapLoadedListener { (begin, end) -> _this.handleMapChangedEvent(EventTypes.DID_FINISH_LOADING_MAP) }) - mMap.addOnStyleLoadedListener(OnStyleLoadedListener { (begin, end) -> _this.handleMapChangedEvent(EventTypes.DID_FINISH_LOADING_STYLE) }) - mMap.addOnStyleImageMissingListener(OnStyleImageMissingListener { (begin, end, id) -> + + onMapReady(map) + + map.addOnMapLoadedListener(OnMapLoadedListener { (begin, end) -> _this.handleMapChangedEvent(EventTypes.DID_FINISH_LOADING_MAP) }) + map.addOnStyleLoadedListener(OnStyleLoadedListener { (begin, end) -> _this.handleMapChangedEvent(EventTypes.DID_FINISH_LOADING_STYLE) }) + map.addOnStyleImageMissingListener(OnStyleImageMissingListener { (begin, end, id) -> for (images in mImages) { - if (images.addMissingImageToStyle(id, mMap)) { + if (images.addMissingImageToStyle(id, map)) { return@OnStyleImageMissingListener } } for (images in mImages) { - images.sendImageMissingEvent(id, mMap) + images.sendImageMissingEvent(id, map) } }) RNMBXMarkerViewManager.markerViewContainerSizeFixer(this, mapView.viewAnnotationManager) - this.addOnLayoutChangeListener(this) - this.setupEvents() + this.setupEvents(map) + return mapView + } + + init { + offscreenAnnotationViewContainer = FrameLayout(getContext()) + val p = FrameLayout.LayoutParams(0, 0) + p.setMargins(-10000, -10000, -10000, -10000) + offscreenAnnotationViewContainer?.setLayoutParams(p) + addView(offscreenAnnotationViewContainer) + + mSources = HashMap() + mImages = ArrayList() + mPointAnnotations = HashMap() } // region Ornaments @@ -1259,30 +1323,30 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie fun setReactCompassEnabled(compassEnabled: Boolean) { mCompassSettings.enabled = compassEnabled - updateCompass() + changes.add(Property.COMPASS) } fun setReactCompassFadeWhenNorth(compassFadeWhenNorth: Boolean) { mCompassFadeWhenNorth = compassFadeWhenNorth - updateCompass() + changes.add(Property.COMPASS) } fun setReactCompassViewMargins(compassViewMargins: ReadableMap) { mCompassSettings.margins = compassViewMargins - updateCompass() + changes.add(Property.COMPASS) } fun setReactCompassViewPosition(compassViewPosition: Int) { mCompassSettings.position = compassViewPosition - updateCompass() + changes.add(Property.COMPASS) } fun setReactCompassPosition(compassPosition: ReadableMap) { mCompassSettings.setPosAndMargins(compassPosition) - updateCompass() + changes.add(Property.COMPASS) } - private fun updateCompass() { + private fun applyCompass() { mapView.compass.updateSettings { fadeWhenFacingNorth = mCompassFadeWhenNorth updateOrnament("compass", mCompassSettings, this.toGenericOrnamentSettings()) @@ -1294,25 +1358,25 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie fun setReactScaleBarEnabled(scaleBarEnabled: Boolean) { mScaleBarSettings.enabled = scaleBarEnabled - updateScaleBar() + changes.add(Property.SCALEBAR) } fun setReactScaleBarViewMargins(scaleBarMargins: ReadableMap) { mScaleBarSettings.margins = scaleBarMargins - updateScaleBar() + changes.add(Property.SCALEBAR) } fun setReactScaleBarViewPosition(scaleBarPosition: Int) { mScaleBarSettings.position = scaleBarPosition - updateScaleBar() + changes.add(Property.SCALEBAR) } fun setReactScaleBarPosition(scaleBarPosition: ReadableMap) { mScaleBarSettings.setPosAndMargins(scaleBarPosition) - updateScaleBar() + changes.add(Property.SCALEBAR) } - private fun updateScaleBar() { + private fun applyScaleBar() { mapView.scalebar.updateSettings { updateOrnament("scaleBar", mScaleBarSettings, this.toGenericOrnamentSettings()) } @@ -1365,25 +1429,25 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie fun setReactAttributionEnabled(attributionEnabled: Boolean?) { mAttributionSettings.enabled = attributionEnabled - updateAttribution() + changes.add(Property.ATTRIBUTION) } fun setReactAttributionViewMargins(margins: ReadableMap) { mAttributionSettings.margins = margins - updateAttribution() + changes.add(Property.ATTRIBUTION) } fun setReactAttributionViewPosition(position: Int) { mAttributionSettings.position = position - updateAttribution() + changes.add(Property.ATTRIBUTION) } fun setReactAttributionPosition(position: ReadableMap?) { mAttributionSettings.setPosAndMargins(position) - updateAttribution() + changes.add(Property.ATTRIBUTION) } - private fun updateAttribution() { + private fun applyAttribution() { mapView.attribution.updateSettings { updateOrnament("attribution", mAttributionSettings, this.toGenericOrnamentSettings()) } @@ -1400,25 +1464,25 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie fun setReactLogoEnabled(enabled: Boolean?) { mLogoSettings.enabled = enabled - updateLogo() + changes.add(Property.LOGO) } fun setReactLogoMargins(margins: ReadableMap) { mLogoSettings.margins = margins - updateLogo() + changes.add(Property.LOGO) } fun setReactLogoViewPosition(position: Int) { mLogoSettings.position = position - updateLogo() + changes.add(Property.LOGO) } fun setReactLogoPosition(position: ReadableMap?) { mLogoSettings.setPosAndMargins(position) - updateLogo() + changes.add(Property.LOGO) } - private fun updateLogo() { + private fun applyLogo() { mapView.logo.updateSettings { updateOrnament("logo", mLogoSettings, this.toGenericOrnamentSettings()) } diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapViewManager.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapViewManager.kt index 44cb245aa..c1a990bad 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapViewManager.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapViewManager.kt @@ -77,7 +77,9 @@ open class RNMBXMapViewManager(context: ReactApplicationContext, val viewTagReso override fun onAfterUpdateTransaction(mapView: RNMBXMapView) { super.onAfterUpdateTransaction(mapView) - if (mapView.getMapboxMap() == null) { + val first = !mapView.isInitialized + mapView.applyAllChanges() + if (first) { mViews[mapView.id] = mapView mapView.init() } @@ -141,53 +143,63 @@ open class RNMBXMapViewManager(context: ReactApplicationContext, val viewTagReso mapView.setReactLocalizeLabels(locale, layerIds) } + @ReactProp(name = "surfaceView") + override fun setSurfaceView(mapView: RNMBXMapView, value: Dynamic) { + if (mapView.isInitialized) { + Logger.d(LOG_TAG, "setSurafaceView cannot be changed") + } else { + mapView.surfaceView = value.asBoolean() + } + } + @ReactProp(name = "gestureSettings") override fun setGestureSettings(mapView: RNMBXMapView, settings: Dynamic) { - mapView.getMapboxMap().gesturesPlugin { - val map = settings.asMap() - this.updateSettings { - map.getAndLogIfNotBoolean("doubleTapToZoomInEnabled", LOG_TAG)?.let { - this.doubleTapToZoomInEnabled = it - } - map.getAndLogIfNotBoolean("doubleTouchToZoomOutEnabled", LOG_TAG)?.let { - this.doubleTouchToZoomOutEnabled = it - } - map.getAndLogIfNotBoolean("pinchPanEnabled", LOG_TAG)?.let { - this.pinchScrollEnabled = it - } - map.getAndLogIfNotBoolean("pinchZoomEnabled", LOG_TAG)?.let { - this.pinchToZoomEnabled = it - } - map.getAndLogIfNotBoolean("pinchZoomDecelerationEnabled", LOG_TAG)?.let { - this.pinchToZoomDecelerationEnabled = it - } - map.getAndLogIfNotBoolean("pitchEnabled", LOG_TAG)?.let { - this.pitchEnabled = it - } - map.getAndLogIfNotBoolean("quickZoomEnabled", LOG_TAG)?.let { - this.quickZoomEnabled = it - } - map.getAndLogIfNotBoolean("rotateEnabled", LOG_TAG)?.let { - this.rotateEnabled = it - } - map.getAndLogIfNotBoolean("rotateDecelerationEnabled", LOG_TAG)?.let { - this.rotateDecelerationEnabled = it - } - map.getAndLogIfNotBoolean("panEnabled", LOG_TAG)?.let { - this.scrollEnabled = it - } - map.getAndLogIfNotDouble("panDecelerationFactor", LOG_TAG)?.let { - this.scrollDecelerationEnabled = it > 0.0 - } - map.getAndLogIfNotBoolean("simultaneousRotateAndPinchToZoomEnabled", LOG_TAG)?.let { - this.simultaneousRotateAndPinchToZoomEnabled = it - } - map.getAndLogIfNotDouble("zoomAnimationAmount", LOG_TAG)?.let { - this.zoomAnimationAmount = it.toFloat() - } - } + mapView.withMap { + it.gesturesPlugin { + val map = settings.asMap() + this.updateSettings { + map.getAndLogIfNotBoolean("doubleTapToZoomInEnabled", LOG_TAG)?.let { + this.doubleTapToZoomInEnabled = it + } + map.getAndLogIfNotBoolean("doubleTouchToZoomOutEnabled", LOG_TAG)?.let { + this.doubleTouchToZoomOutEnabled = it + } + map.getAndLogIfNotBoolean("pinchPanEnabled", LOG_TAG)?.let { + this.pinchScrollEnabled = it + } + map.getAndLogIfNotBoolean("pinchZoomEnabled", LOG_TAG)?.let { + this.pinchToZoomEnabled = it + } + map.getAndLogIfNotBoolean("pinchZoomDecelerationEnabled", LOG_TAG)?.let { + this.pinchToZoomDecelerationEnabled = it + } + map.getAndLogIfNotBoolean("pitchEnabled", LOG_TAG)?.let { + this.pitchEnabled = it + } + map.getAndLogIfNotBoolean("quickZoomEnabled", LOG_TAG)?.let { + this.quickZoomEnabled = it + } + map.getAndLogIfNotBoolean("rotateEnabled", LOG_TAG)?.let { + this.rotateEnabled = it + } + map.getAndLogIfNotBoolean("rotateDecelerationEnabled", LOG_TAG)?.let { + this.rotateDecelerationEnabled = it + } + map.getAndLogIfNotBoolean("panEnabled", LOG_TAG)?.let { + this.scrollEnabled = it + } + map.getAndLogIfNotDouble("panDecelerationFactor", LOG_TAG)?.let { + this.scrollDecelerationEnabled = it > 0.0 + } + map.getAndLogIfNotBoolean("simultaneousRotateAndPinchToZoomEnabled", LOG_TAG)?.let { + this.simultaneousRotateAndPinchToZoomEnabled = it + } + map.getAndLogIfNotDouble("zoomAnimationAmount", LOG_TAG)?.let { + this.zoomAnimationAmount = it.toFloat() + } + } + } } - } @ReactProp(name = "styleURL") @@ -202,28 +214,32 @@ open class RNMBXMapViewManager(context: ReactApplicationContext, val viewTagReso @ReactProp(name = "zoomEnabled") override fun setZoomEnabled(map: RNMBXMapView, zoomEnabled: Dynamic) { - val mapView = map.mapView - mapView.gestures.pinchToZoomEnabled = zoomEnabled.asBoolean() - mapView.gestures.doubleTouchToZoomOutEnabled = zoomEnabled.asBoolean() - mapView.gestures.doubleTapToZoomInEnabled = zoomEnabled.asBoolean() + map.withMapView { + it.gestures.pinchToZoomEnabled = zoomEnabled.asBoolean() + it.gestures.doubleTouchToZoomOutEnabled = zoomEnabled.asBoolean() + it.gestures.doubleTapToZoomInEnabled = zoomEnabled.asBoolean() + } } @ReactProp(name = "scrollEnabled") override fun setScrollEnabled(map: RNMBXMapView, scrollEnabled: Dynamic) { - val mapView = map.mapView - mapView.gestures.scrollEnabled = scrollEnabled.asBoolean() + map.withMapView { + it.gestures.scrollEnabled = scrollEnabled.asBoolean() + } } @ReactProp(name = "pitchEnabled") override fun setPitchEnabled(map: RNMBXMapView, pitchEnabled: Dynamic) { - val mapView = map.mapView - mapView.gestures.pitchEnabled = pitchEnabled.asBoolean() + map.withMapView { + it.gestures.pitchEnabled = pitchEnabled.asBoolean() + } } @ReactProp(name = "rotateEnabled") override fun setRotateEnabled(map: RNMBXMapView, rotateEnabled: Dynamic) { - val mapView = map.mapView - mapView.gestures.rotateEnabled = rotateEnabled.asBoolean() + map.withMapView { + it.gestures.rotateEnabled = rotateEnabled.asBoolean() + } } @ReactProp(name = "attributionEnabled") diff --git a/android/src/main/java/com/rnmapbox/rnmbx/utils/PropertyChanges.kt b/android/src/main/java/com/rnmapbox/rnmbx/utils/PropertyChanges.kt new file mode 100644 index 000000000..e72097673 --- /dev/null +++ b/android/src/main/java/com/rnmapbox/rnmbx/utils/PropertyChanges.kt @@ -0,0 +1,68 @@ +package com.rnmapbox.rnmbx.utils + +/** + * This mechanism allows to separate property updates from application of property updates. Usefull for delaying the propery updates + * because the object is not yet created for example. Or to apply multiple propery changes at once. + * + * @sample + * + * class MapView { + * enum class Property(_apply: (MapView)->Unit) : PropertyUpdaterWithName { + * class LOGO_POSITION(MapView.applyLogoPosition) + * + * override fun apply(mapView: MapView): Unit { + * _apply(mapView) + * } + * } + * val changes: PropertyUpdates() + * + * var logoPosition: LogoPosition; + * + * fun setLogoPosition(value: LogoPosition) { + * logoPosition = value + * changes.add(Property::LOGO_POSITION) + * } + * + * fun setGestureSettings(value: Custom) { + * changes.add(Property::CUSTOM("gestures") { + * mapboxMap.updateGestures(...) + * }) + * } + * + * fun applyLogoPosition() { + * mapboxMap.updateLogoPosition(logoPosition) + * } + * } + * } + */ + +interface PropertyUpdater { + fun apply(item: Base): Unit; +} +interface PropertyUpdaterWithName : PropertyUpdater { + val name: String; +} + +class CustomPropUpdater(val _apply: (T) -> Unit) : PropertyUpdater { + override fun apply(item: T): Unit { + _apply(item) + } +} +class PropertyChanges { + val changes = mutableMapOf>(); + + fun add(change: PropertyUpdaterWithName) { + changes.set(change.name, change) + } + + fun add(key: String, apply: (T) -> Unit) { + changes.set(key, CustomPropUpdater(apply)) + } + + fun apply(target: T) { + for (entry in changes.entries.iterator()) { + print("key => ${entry.key}") + entry.value.apply(target) + } + } +} \ No newline at end of file diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXAndroidTextureMapViewManagerDelegate.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXAndroidTextureMapViewManagerDelegate.java deleted file mode 100644 index 6da9f7929..000000000 --- a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXAndroidTextureMapViewManagerDelegate.java +++ /dev/null @@ -1,95 +0,0 @@ -/** -* 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 RNMBXAndroidTextureMapViewManagerDelegate & RNMBXAndroidTextureMapViewManagerInterface> extends BaseViewManagerDelegate { - public RNMBXAndroidTextureMapViewManagerDelegate(U viewManager) { - super(viewManager); - } - @Override - public void setProperty(T view, String propName, @Nullable Object value) { - switch (propName) { - case "attributionEnabled": - mViewManager.setAttributionEnabled(view, new DynamicFromObject(value)); - break; - case "attributionPosition": - mViewManager.setAttributionPosition(view, new DynamicFromObject(value)); - break; - case "logoEnabled": - mViewManager.setLogoEnabled(view, new DynamicFromObject(value)); - break; - case "logoPosition": - mViewManager.setLogoPosition(view, new DynamicFromObject(value)); - break; - case "compassEnabled": - mViewManager.setCompassEnabled(view, new DynamicFromObject(value)); - break; - case "compassFadeWhenNorth": - mViewManager.setCompassFadeWhenNorth(view, new DynamicFromObject(value)); - break; - case "compassPosition": - mViewManager.setCompassPosition(view, new DynamicFromObject(value)); - break; - case "compassViewPosition": - mViewManager.setCompassViewPosition(view, new DynamicFromObject(value)); - break; - case "compassViewMargins": - mViewManager.setCompassViewMargins(view, new DynamicFromObject(value)); - break; - case "scaleBarEnabled": - mViewManager.setScaleBarEnabled(view, new DynamicFromObject(value)); - break; - case "scaleBarPosition": - mViewManager.setScaleBarPosition(view, new DynamicFromObject(value)); - break; - case "zoomEnabled": - mViewManager.setZoomEnabled(view, new DynamicFromObject(value)); - break; - case "scrollEnabled": - mViewManager.setScrollEnabled(view, new DynamicFromObject(value)); - break; - case "rotateEnabled": - mViewManager.setRotateEnabled(view, new DynamicFromObject(value)); - break; - case "pitchEnabled": - mViewManager.setPitchEnabled(view, new DynamicFromObject(value)); - break; - case "requestDisallowInterceptTouchEvent": - mViewManager.setRequestDisallowInterceptTouchEvent(view, new DynamicFromObject(value)); - break; - case "projection": - mViewManager.setProjection(view, new DynamicFromObject(value)); - break; - case "localizeLabels": - mViewManager.setLocalizeLabels(view, new DynamicFromObject(value)); - break; - case "styleURL": - mViewManager.setStyleURL(view, new DynamicFromObject(value)); - break; - case "scaleBarViewMargins": - mViewManager.setScaleBarViewMargins(view, new DynamicFromObject(value)); - break; - case "attributionViewMargins": - mViewManager.setAttributionViewMargins(view, new DynamicFromObject(value)); - break; - case "attributionViewPosition": - mViewManager.setAttributionViewPosition(view, new DynamicFromObject(value)); - break; - default: - super.setProperty(view, propName, value); - } - } -} diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXAndroidTextureMapViewManagerInterface.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXAndroidTextureMapViewManagerInterface.java deleted file mode 100644 index f1b7aeb51..000000000 --- a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXAndroidTextureMapViewManagerInterface.java +++ /dev/null @@ -1,38 +0,0 @@ -/** -* 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 RNMBXAndroidTextureMapViewManagerInterface { - void setAttributionEnabled(T view, Dynamic value); - void setAttributionPosition(T view, Dynamic value); - void setLogoEnabled(T view, Dynamic value); - void setLogoPosition(T view, Dynamic value); - void setCompassEnabled(T view, Dynamic value); - void setCompassFadeWhenNorth(T view, Dynamic value); - void setCompassPosition(T view, Dynamic value); - void setCompassViewPosition(T view, Dynamic value); - void setCompassViewMargins(T view, Dynamic value); - void setScaleBarEnabled(T view, Dynamic value); - void setScaleBarPosition(T view, Dynamic value); - void setZoomEnabled(T view, Dynamic value); - void setScrollEnabled(T view, Dynamic value); - void setRotateEnabled(T view, Dynamic value); - void setPitchEnabled(T view, Dynamic value); - void setRequestDisallowInterceptTouchEvent(T view, Dynamic value); - void setProjection(T view, Dynamic value); - void setLocalizeLabels(T view, Dynamic value); - void setStyleURL(T view, Dynamic value); - void setScaleBarViewMargins(T view, Dynamic value); - void setAttributionViewMargins(T view, Dynamic value); - void setAttributionViewPosition(T view, Dynamic value); -} diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXMapViewManagerDelegate.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXMapViewManagerDelegate.java index 84028e170..c09acf65f 100644 --- a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXMapViewManagerDelegate.java +++ b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXMapViewManagerDelegate.java @@ -82,6 +82,9 @@ public void setProperty(T view, String propName, @Nullable Object value) { case "gestureSettings": mViewManager.setGestureSettings(view, new DynamicFromObject(value)); break; + case "surfaceView": + mViewManager.setSurfaceView(view, new DynamicFromObject(value)); + break; case "scaleBarViewMargins": mViewManager.setScaleBarViewMargins(view, new DynamicFromObject(value)); break; diff --git a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXMapViewManagerInterface.java b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXMapViewManagerInterface.java index a92d2e0d2..13388a15d 100644 --- a/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXMapViewManagerInterface.java +++ b/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXMapViewManagerInterface.java @@ -33,6 +33,7 @@ public interface RNMBXMapViewManagerInterface { void setLocalizeLabels(T view, Dynamic value); void setStyleURL(T view, Dynamic value); void setGestureSettings(T view, Dynamic value); + void setSurfaceView(T view, Dynamic value); void setScaleBarViewMargins(T view, Dynamic value); void setAttributionViewMargins(T view, Dynamic value); void setAttributionViewPosition(T view, Dynamic value); diff --git a/src/components/MapView.tsx b/src/components/MapView.tsx index d31f1828f..b50c255f4 100644 --- a/src/components/MapView.tsx +++ b/src/components/MapView.tsx @@ -13,7 +13,6 @@ import { debounce } from 'debounce'; import { GeoJsonProperties, Geometry } from 'geojson'; import NativeMapView from '../specs/RNMBXMapViewNativeComponent'; -import NativeAndroidTextureMapView from '../specs/RNMBXAndroidTextureMapViewNativeComponent'; import NativeMapViewModule from '../specs/NativeMapViewModule'; import { isFunction, @@ -926,7 +925,7 @@ class MapView extends NativeBridgeComponent( } } - _onPress(e: NativeSyntheticEvent<{ payload: GeoJSON.Feature }>) { + _onPress(e: NativeSyntheticEvent<{ payload: GeoJSON.Feature | string }>) { if (isFunction(this.props.onPress)) { this.props.onPress(this._decodePayload(e.nativeEvent.payload)); } @@ -1091,9 +1090,11 @@ class MapView extends NativeBridgeComponent( return this.props.contentInset; } - _setNativeRef(nativeRef: RNMBXMapViewRefType) { - this._nativeRef = nativeRef; - super._runPendingNativeMethods(nativeRef); + _setNativeRef(nativeRef: RNMBXMapViewRefType | null) { + if (nativeRef != null) { + this._nativeRef = nativeRef; + super._runPendingNativeMethods(nativeRef); + } } setNativeProps(props: NativeProps) { @@ -1142,7 +1143,8 @@ class MapView extends NativeBridgeComponent( this._setLocalizeLabels(props); const callbacks = { - ref: (nativeRef: RNMBXMapViewRefType) => this._setNativeRef(nativeRef), + ref: (nativeRef: RNMBXMapViewRefType | null) => + this._setNativeRef(nativeRef), onPress: this._onPress, onLongPress: this._onLongPress, onMapChange: this._onChange, @@ -1150,16 +1152,8 @@ class MapView extends NativeBridgeComponent( }; let mapView = null; - if (isAndroid() && !this.props.surfaceView && this.state.isReady) { + if (this.state.isReady) { mapView = ( - - {this.props.children} - - ); - } else if (this.state.isReady) { - mapView = ( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore TODO: fix types {this.props.children} @@ -1182,19 +1176,18 @@ type NativeProps = Omit< Props, 'onPress' | 'onLongPress' | 'onCameraChanged' > & { - onPress(event: NativeSyntheticEvent<{ payload: GeoJSON.Feature }>): void; - onLongPress(event: NativeSyntheticEvent<{ payload: GeoJSON.Feature }>): void; - onCameraChanged(event: NativeSyntheticEvent<{ payload: MapState }>): void; + onPress?: ( + event: NativeSyntheticEvent<{ type: string; payload: string }>, + ) => void; + onLongPress?: ( + event: NativeSyntheticEvent<{ type: string; payload: string }>, + ) => void; + onCameraChanged?: ( + event: NativeSyntheticEvent<{ type: string; payload: string }>, + ) => void; }; type RNMBXMapViewRefType = Component & Readonly; -// const RNMBXMapView = requireNativeComponent(NATIVE_MODULE_NAME); -// TODO: figure out how to pick the correct implementation const RNMBXMapView = NativeMapView; -let RNMBXAndroidTextureMapView: any; -if (isAndroid()) { - RNMBXAndroidTextureMapView = NativeAndroidTextureMapView; -} - export default MapView; diff --git a/src/specs/RNMBXAndroidTextureMapViewNativeComponent.ts b/src/specs/RNMBXAndroidTextureMapViewNativeComponent.ts deleted file mode 100644 index 8ff4b0619..000000000 --- a/src/specs/RNMBXAndroidTextureMapViewNativeComponent.ts +++ /dev/null @@ -1,59 +0,0 @@ -import type { HostComponent, ViewProps } from 'react-native'; -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; -import { - DirectEventHandler, - Int32, -} from 'react-native/Libraries/Types/CodegenTypes'; - -import type { LocalizeLabels, Point, UnsafeMixed } from './codegenUtils'; - -type OnCameraChangedEventType = { type: string; payload: string }; -type OnPressEventType = { type: string; payload: string }; -type OnMapChangeEventType = { type: string; payload: string }; - -export interface NativeProps extends ViewProps { - onCameraChanged?: DirectEventHandler; - - attributionEnabled?: UnsafeMixed; - attributionPosition?: UnsafeMixed; - - logoEnabled?: UnsafeMixed; - logoPosition?: UnsafeMixed; - - compassEnabled?: UnsafeMixed; - compassFadeWhenNorth?: UnsafeMixed; - compassPosition?: UnsafeMixed; - compassViewPosition?: UnsafeMixed; - compassViewMargins?: UnsafeMixed; - - scaleBarEnabled?: UnsafeMixed; - scaleBarPosition?: UnsafeMixed; - - zoomEnabled?: UnsafeMixed; - scrollEnabled?: UnsafeMixed; - rotateEnabled?: UnsafeMixed; - pitchEnabled?: UnsafeMixed; - - requestDisallowInterceptTouchEvent?: UnsafeMixed; - - projection?: UnsafeMixed; - localizeLabels?: UnsafeMixed; - - styleURL?: UnsafeMixed; - - // Android only - scaleBarViewMargins?: UnsafeMixed; - attributionViewMargins?: UnsafeMixed; - attributionViewPosition?: UnsafeMixed; - - onPress?: DirectEventHandler; - onLongPress?: DirectEventHandler; - onMapChange?: DirectEventHandler; -} - -export default codegenNativeComponent( - 'RNMBXAndroidTextureMapView', - { - excludedPlatforms: ['iOS'], - }, -) as HostComponent; diff --git a/src/specs/RNMBXMapViewNativeComponent.ts b/src/specs/RNMBXMapViewNativeComponent.ts index 0d4da8e53..311be327a 100644 --- a/src/specs/RNMBXMapViewNativeComponent.ts +++ b/src/specs/RNMBXMapViewNativeComponent.ts @@ -5,7 +5,7 @@ import { Int32, } from 'react-native/Libraries/Types/CodegenTypes'; -import type { LocalizeLabels, Point, UnsafeMixed } from './codegenUtils'; +import type { Point, UnsafeMixed } from './codegenUtils'; // see https://github.com/rnmapbox/maps/wiki/FabricOptionalProp type OptionalProp = UnsafeMixed; @@ -17,7 +17,38 @@ type GestureSettings = { pinchToZoomDecelerationEnabled?: boolean; }; -type OnCameraChangedEventType = { type: string; payload: string }; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +type MapState = { + properties: { + center: GeoJSON.Position; + bounds: { + ne: GeoJSON.Position; + sw: GeoJSON.Position; + }; + zoom: number; + heading: number; + pitch: number; + }; + gestures: { + isGestureActive: boolean; + }; + timestamp?: number; +}; + +type LocalizeLabels = + | { + locale: string; + layerIds?: string[]; + } + | true; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +type PayloadType<_T> = string; + +type OnCameraChangedEventType = { + type: string; + payload: string /* | MapState */; +}; type OnPressEventType = { type: string; payload: string }; type OnMapChangeEventType = { type: string; payload: string }; @@ -46,7 +77,7 @@ export interface NativeProps extends ViewProps { requestDisallowInterceptTouchEvent?: OptionalProp; - projection?: OptionalProp; + projection?: OptionalProp<'mercator' | 'globe'>; localizeLabels?: UnsafeMixed; styleURL?: OptionalProp; @@ -54,6 +85,7 @@ export interface NativeProps extends ViewProps { gestureSettings?: UnsafeMixed; // Android only + surfaceView?: OptionalProp; scaleBarViewMargins?: UnsafeMixed; attributionViewMargins?: UnsafeMixed; attributionViewPosition?: UnsafeMixed; diff --git a/src/specs/codegenUtils.ts b/src/specs/codegenUtils.ts index 54396c9f1..a15d962c3 100644 --- a/src/specs/codegenUtils.ts +++ b/src/specs/codegenUtils.ts @@ -14,11 +14,6 @@ export type Point = { y: Int32; }; -export type LocalizeLabels = { - locale: string; - layerIds?: string[]; -}; - export type NativeCameraStop = { centerCoordinate?: string; bounds?: string; From 7c69f7ffb42fac652bfa50cbe8f43623dc66c37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 26 Oct 2023 17:27:01 +0200 Subject: [PATCH 2/4] fix: use_frameworks - use rnmapbox_maps-Swift.pre.h --- ios/RNMBX/RNMBXFabricHelpers.h | 9 +-------- ios/RNMBX/RNMBXImageModule.mm | 10 +--------- ios/RNMBX/RNMBXPointAnnotationModule.mm | 10 +--------- ios/RNMBX/RNMBXShapeSourceModule.mm | 10 +--------- ios/RNMBX/rnmapbox_maps-Swift.pre.h | 2 -- 5 files changed, 4 insertions(+), 37 deletions(-) diff --git a/ios/RNMBX/RNMBXFabricHelpers.h b/ios/RNMBX/RNMBXFabricHelpers.h index 256472289..bf076072c 100644 --- a/ios/RNMBX/RNMBXFabricHelpers.h +++ b/ios/RNMBX/RNMBXFabricHelpers.h @@ -2,14 +2,7 @@ #import #import -// needed for compilation for some reason -#import -#import - -@interface MapView : UIView -@end - -#import +#import "rnmapbox_maps-Swift.pre.h" // copied from RCTFollyConvert static id RNMBXConvertFollyDynamicToId(const folly::dynamic &dyn) diff --git a/ios/RNMBX/RNMBXImageModule.mm b/ios/RNMBX/RNMBXImageModule.mm index 83e7dcbe3..f5a41d38b 100644 --- a/ios/RNMBX/RNMBXImageModule.mm +++ b/ios/RNMBX/RNMBXImageModule.mm @@ -7,15 +7,7 @@ #import "RNMBXImageComponentView.h" #endif // RCT_NEW_ARCH_ENABLED -// needed for compilation for some reason -#import -#import - -@interface MapView : UIView -@end - -#import - +#import "rnmapbox_maps-Swift.pre.h" @implementation RNMBXImageModule diff --git a/ios/RNMBX/RNMBXPointAnnotationModule.mm b/ios/RNMBX/RNMBXPointAnnotationModule.mm index 210b30119..2df07a1d0 100644 --- a/ios/RNMBX/RNMBXPointAnnotationModule.mm +++ b/ios/RNMBX/RNMBXPointAnnotationModule.mm @@ -7,15 +7,7 @@ #import "RNMBXPointAnnotationComponentView.h" #endif // RCT_NEW_ARCH_ENABLED -// needed for compilation for some reason -#import -#import - -@interface MapView : UIView -@end - -#import - +#import "rnmapbox_maps-Swift.pre.h" @implementation RNMBXPointAnnotationModule diff --git a/ios/RNMBX/RNMBXShapeSourceModule.mm b/ios/RNMBX/RNMBXShapeSourceModule.mm index fec77f3bd..d779a6ce9 100644 --- a/ios/RNMBX/RNMBXShapeSourceModule.mm +++ b/ios/RNMBX/RNMBXShapeSourceModule.mm @@ -7,15 +7,7 @@ #import "RNMBXShapeSourceComponentView.h" #endif // RCT_NEW_ARCH_ENABLED -// needed for compilation for some reason -#import -#import - -@interface MapView : UIView -@end - -#import - +#import "rnmapbox_maps-Swift.pre.h" @implementation RNMBXShapeSourceModule diff --git a/ios/RNMBX/rnmapbox_maps-Swift.pre.h b/ios/RNMBX/rnmapbox_maps-Swift.pre.h index 131f4b70a..1362c76a3 100644 --- a/ios/RNMBX/rnmapbox_maps-Swift.pre.h +++ b/ios/RNMBX/rnmapbox_maps-Swift.pre.h @@ -1,5 +1,3 @@ -// ideally the file extension would be just `.h` but then it gets picked up as a header part of the umbrella header - #import #import From 1b44d3e4ca838a95b1122074cbbdcab6013d5dc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 26 Oct 2023 22:55:14 +0200 Subject: [PATCH 3/4] fix: correct ts types of codgen on RNMBXMapView --- src/components/MapView.tsx | 32 +++++----- src/specs/RNMBXMapViewNativeComponent.ts | 80 +++++++++++++++++------- 2 files changed, 72 insertions(+), 40 deletions(-) diff --git a/src/components/MapView.tsx b/src/components/MapView.tsx index b50c255f4..111538d28 100644 --- a/src/components/MapView.tsx +++ b/src/components/MapView.tsx @@ -10,9 +10,10 @@ import { LayoutChangeEvent, } from 'react-native'; import { debounce } from 'debounce'; -import { GeoJsonProperties, Geometry } from 'geojson'; -import NativeMapView from '../specs/RNMBXMapViewNativeComponent'; +import NativeMapView, { + type NativeMapViewActual, +} from '../specs/RNMBXMapViewNativeComponent'; import NativeMapViewModule from '../specs/NativeMapViewModule'; import { isFunction, @@ -913,11 +914,7 @@ class MapView extends NativeBridgeComponent( return this._runNative('showAttribution'); } - _decodePayload( - payload: GeoJSON.Feature | string, - ): GeoJSON.Feature { - // 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 + _decodePayload(payload: T | string): T { if (typeof payload === 'string') { return JSON.parse(payload); } else { @@ -931,9 +928,9 @@ class MapView extends NativeBridgeComponent( } } - _onLongPress(e: NativeSyntheticEvent<{ payload: GeoJSON.Feature }>) { + _onLongPress(e: NativeSyntheticEvent<{ payload: GeoJSON.Feature | string }>) { if (isFunction(this.props.onLongPress)) { - this.props.onLongPress(e.nativeEvent.payload); + this.props.onLongPress(this._decodePayload(e.nativeEvent.payload)); } } @@ -960,17 +957,19 @@ class MapView extends NativeBridgeComponent( this.setState({ region: payload }); } - _onCameraChanged(e: NativeSyntheticEvent<{ payload: MapState }>) { - this.props.onCameraChanged?.(e.nativeEvent.payload); + _onCameraChanged(e: NativeSyntheticEvent<{ payload: MapState | string }>) { + this.props.onCameraChanged?.(this._decodePayload(e.nativeEvent.payload)); } _onChange( e: NativeSyntheticEvent<{ type: string; - payload: GeoJSON.Feature< - GeoJSON.Point, - RegionPayload & { isAnimatingFromUserInteraction: boolean } - >; + payload: + | GeoJSON.Feature< + GeoJSON.Point, + RegionPayload & { isAnimatingFromUserInteraction: boolean } + > + | string; }>, ) { const { regionWillChangeDebounceTime, regionDidChangeDebounceTime } = @@ -1188,6 +1187,7 @@ type NativeProps = Omit< }; type RNMBXMapViewRefType = Component & Readonly; -const RNMBXMapView = NativeMapView; + +const RNMBXMapView = NativeMapView as NativeMapViewActual; export default MapView; diff --git a/src/specs/RNMBXMapViewNativeComponent.ts b/src/specs/RNMBXMapViewNativeComponent.ts index 311be327a..09a51f98b 100644 --- a/src/specs/RNMBXMapViewNativeComponent.ts +++ b/src/specs/RNMBXMapViewNativeComponent.ts @@ -17,24 +17,6 @@ type GestureSettings = { pinchToZoomDecelerationEnabled?: boolean; }; -// eslint-disable-next-line @typescript-eslint/no-unused-vars -type MapState = { - properties: { - center: GeoJSON.Position; - bounds: { - ne: GeoJSON.Position; - sw: GeoJSON.Position; - }; - zoom: number; - heading: number; - pitch: number; - }; - gestures: { - isGestureActive: boolean; - }; - timestamp?: number; -}; - type LocalizeLabels = | { locale: string; @@ -42,19 +24,14 @@ type LocalizeLabels = } | true; -// eslint-disable-next-line @typescript-eslint/no-unused-vars -type PayloadType<_T> = string; - type OnCameraChangedEventType = { type: string; - payload: string /* | MapState */; + payload: string; }; type OnPressEventType = { type: string; payload: string }; type OnMapChangeEventType = { type: string; payload: string }; export interface NativeProps extends ViewProps { - onCameraChanged?: DirectEventHandler; - attributionEnabled?: OptionalProp; attributionPosition?: UnsafeMixed; @@ -96,8 +73,63 @@ export interface NativeProps extends ViewProps { onPress?: DirectEventHandler; onLongPress?: DirectEventHandler; onMapChange?: DirectEventHandler; + onCameraChanged?: DirectEventHandler; } export default codegenNativeComponent( 'RNMBXMapView', ) as HostComponent; + +// The actually types for callbacks are sometwhat different due to codegen limitations: + +type MapState = { + properties: { + center: GeoJSON.Position; + bounds: { + ne: GeoJSON.Position; + sw: GeoJSON.Position; + }; + zoom: number; + heading: number; + pitch: number; + }; + gestures: { + isGestureActive: boolean; + }; + timestamp?: number; +}; +type RegionPayload = { + zoomLevel: number; + heading: number; + animated: boolean; + isUserInteraction: boolean; + visibleBounds: GeoJSON.Position[]; + pitch: number; +}; + +type OnPressEventTypeActual = { + type: string; + payload: GeoJSON.Feature | string; +}; +type OnCameraChangedEventTypeActual = { + type: string; + payload: MapState | string; +}; +type OnMapChangeEventTypeActual = { + type: string; + payload: + | GeoJSON.Feature< + GeoJSON.Point, + RegionPayload & { isAnimatingFromUserInteraction: boolean } + > + | string; +}; + +export type NativeMapViewActual = HostComponent< + Omit & { + onCameraChanged?: DirectEventHandler; + onLongPress?: DirectEventHandler; + onPress?: DirectEventHandler; + onMapChange?: DirectEventHandler; + } +>; From a775fc3440a51ceb83cc13d3c18a0e99628ae064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Fri, 27 Oct 2023 06:38:05 +0200 Subject: [PATCH 4/4] fix(ios,v11): some RNMBX_11 were destroyed during the merge of #3136 --- ios/RNMBX/RNMBXImages.swift | 22 +++++++++++++++++----- ios/RNMBX/RNMBXLight.swift | 12 +++++++++++- ios/RNMBX/RNMBXNativeUserLocation.swift | 4 ++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/ios/RNMBX/RNMBXImages.swift b/ios/RNMBX/RNMBXImages.swift index 04aeb69af..e4957aefc 100644 --- a/ios/RNMBX/RNMBXImages.swift +++ b/ios/RNMBX/RNMBXImages.swift @@ -4,6 +4,18 @@ protocol RNMBXImageSetter : AnyObject { func addImage(name: String, image: UIImage, sdf: Bool?, stretchX: [[NSNumber]], stretchY: [[NSNumber]], content: [NSNumber]?, log: String) -> Bool } +func hasImage(style: Style, name: String) -> Bool { + #if RNMBX_11 + return style.imageExists(withId: name) + #else + return (style.styleManager.getStyleImage(forImageId: name) != nil) + #endif +} + +#if RNMBX_11 +typealias StyleImageMissingPayload = StyleImageMissing +#endif + open class RNMBXImages : UIView, RNMBXMapComponent { @objc public weak var bridge : RCTBridge! = nil @@ -104,9 +116,9 @@ open class RNMBXImages : UIView, RNMBXMapComponent { if !sameImage(oldValue: oldImages[name], newValue: images[name]) { missingImages[name] = images[name] } else { - if style.styleManager.getStyleImage(forImageId: name) == nil { + if hasImage(style: style, name: name) { logged("RNMBXImages.addImagePlaceholder") { - try? style.addImage(placeholderImage, id: name, stretchX: [], stretchY: []) + try style.addImage(placeholderImage, id: name, stretchX: [], stretchY: []) missingImages[name] = images[name] } } @@ -125,7 +137,7 @@ open class RNMBXImages : UIView, RNMBXMapComponent { } } - public func addMissingImageToStyle(style: Style, imageName: String) -> Bool { + internal func addMissingImageToStyle(style: Style, imageName: String) -> Bool { if let nativeImage = nativeImageInfos.first(where: { $0.name == imageName }) { addNativeImages(style: style, nativeImages: [nativeImage]) return true @@ -138,7 +150,7 @@ open class RNMBXImages : UIView, RNMBXMapComponent { return false } - public func sendImageMissingEvent(imageName: String, payload: StyleImageMissingPayload) { + internal func sendImageMissingEvent(imageName: String, payload: StyleImageMissingPayload) { let payload = ["imageKey":imageName] let event = RNMBXEvent(type: .imageMissing, payload: payload) if let onImageMissing = onImageMissing { @@ -231,7 +243,7 @@ open class RNMBXImages : UIView, RNMBXMapComponent { func addNativeImages(style: Style, nativeImages: [NativeImageInfo]) { for imageInfo in nativeImages { let imageName = imageInfo.name - if style.styleManager.getStyleImage(forImageId: imageInfo.name) == nil { + if hasImage(style: style, name:imageName) { if let image = UIImage(named: imageName) { logged("RNMBXImage.addNativeImage: \(imageName)") { try style.addImage(image, id: imageName, sdf: imageInfo.sdf, diff --git a/ios/RNMBX/RNMBXLight.swift b/ios/RNMBX/RNMBXLight.swift index a18e672ab..202a57e18 100644 --- a/ios/RNMBX/RNMBXLight.swift +++ b/ios/RNMBX/RNMBXLight.swift @@ -1,5 +1,9 @@ import MapboxMaps +#if RNMBX_11 +typealias Light = FlatLight +#endif + @objc(RNMBXLight) public class RNMBXLight: UIView, RNMBXMapComponent { @objc public weak var bridge : RCTBridge! = nil @@ -19,7 +23,13 @@ public class RNMBXLight: UIView, RNMBXMapComponent { func apply(light: Light) { let lightData = try! JSONEncoder().encode(light) let lightDictionary = try! JSONSerialization.jsonObject(with: lightData) - try! self.map.style.setLight(properties: lightDictionary as! [String:Any]) + logged("RNMBXLight.apply") { +#if RNMBX_11 + try self.map.setLights(light) +#else + try! self.map.style.setLight(properties: lightDictionary as! [String:Any]) +#endif + } } func addStyles() { diff --git a/ios/RNMBX/RNMBXNativeUserLocation.swift b/ios/RNMBX/RNMBXNativeUserLocation.swift index 0e052b24f..2443154aa 100644 --- a/ios/RNMBX/RNMBXNativeUserLocation.swift +++ b/ios/RNMBX/RNMBXNativeUserLocation.swift @@ -18,7 +18,11 @@ public class RNMBXNativeUserLocation : UIView, RNMBXMapComponent { func _applySettings(_ map: RNMBXMapView) { map.location.options.puckType = .puck2D(.makeDefault(showBearing: iosShowsUserHeadingIndicator)) if (iosShowsUserHeadingIndicator) { + #if RNMBX_11 + map.location.options.puckBearing = .heading + #else map.location.options.puckBearingSource = .heading + #endif map.location.options.puckBearingEnabled = true } else { map.location.options.puckBearingEnabled = false