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] 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;