also looking at this
feat(maps): add key-free native Android maps and shared map controls
#363
28 files
+1857
-481
Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.
| @@ -607,7 +607,7 @@ jobs: | ||
| 607 | 607 | api-level: ${{ fromJSON((inputs.scope != 'android-navigation' || inputs.android_suite == 'full') && '[34,35]' || inputs.android_suite == 'system-bars' && '[35]' || '[34]') }} |
| 608 | 608 | env: |
| 609 | 609 | CRAFT_ANDROID_NATIVE_SUITE: ${{ inputs.scope != 'android-navigation' && 'full' || inputs.android_suite || 'focused' }} |
| 610 | CRAFT_ANDROID_TEST_CLASS: ${{ inputs.scope == 'android-navigation' && inputs.android_suite == 'maps' && 'dev.craft.navigationtest.NativeMapTest#keyFreeBasemapsKeepTheRecordedRouteAndDirectionSignsVisible,dev.craft.navigationtest.NativeMapTest#nativeMapMutationsUpdateThePinAndCameraWithoutReloadingTheStyle,dev.craft.navigationtest.NativeMapTest#showingTheLocationDotDoesNotRequestPermissionDuringRendering,dev.craft.navigationtest.NativeMapTest#controlledRegionEchoPreservesTheCameraAfterANativeDrag' || inputs.scope == 'android-navigation' && inputs.android_suite == 'system-bars' && 'dev.craft.navigationtest.NativeNavigationTest#nativeScreenBackgroundOptionAppliesAndResets' || inputs.scope == 'android-navigation' && inputs.android_suite != 'full' && 'dev.craft.navigationtest.NativeNavigationTest#outgoingTabTapWinsOverSettlingSwipe,dev.craft.navigationtest.NativeNavigationTest#thirdTabTapWinsOverSettlingSwipe,dev.craft.navigationtest.NativeNavigationTest#cancelledSwipeTargetIsVisibleWhenSelectedLater,dev.craft.navigationtest.NativeNavigationTest#completedReverseSwipeKeepsRetainedTabVisible,dev.craft.navigationtest.NativeNavigationTest#nativePullToRefreshSurvivesViewReattachment,dev.craft.navigationtest.NativeNavigationTest#pushedScreenTabAccessoryOpensNativeRouteAndClearsOnBack,dev.craft.navigationtest.NativeFlatListTest#refreshAppearanceUsesTheScreenContrastFallback,dev.craft.navigationtest.NativeNavigationTest#nativeDatePickerKeepsFollowingControlsMounted' || '' }} | |
| 610 | CRAFT_ANDROID_TEST_CLASS: ${{ inputs.scope == 'android-navigation' && inputs.android_suite == 'maps' && 'dev.craft.navigationtest.NativeMapTest#keyFreeBasemapsKeepTheRecordedRouteAndDirectionSignsVisible,dev.craft.navigationtest.NativeMapTest#nativeMapMutationsUpdateThePinAndCameraWithoutReloadingTheStyle,dev.craft.navigationtest.NativeMapTest#showingTheLocationDotDoesNotRequestPermissionDuringRendering,dev.craft.navigationtest.NativeMapTest#controlledRegionEchoPreservesTheCameraAfterANativeDrag,dev.craft.navigationtest.NativeMapTest#backgroundAndResumeKeepTheNativeMapAndCamera' || inputs.scope == 'android-navigation' && inputs.android_suite == 'system-bars' && 'dev.craft.navigationtest.NativeNavigationTest#nativeScreenBackgroundOptionAppliesAndResets' || inputs.scope == 'android-navigation' && inputs.android_suite != 'full' && 'dev.craft.navigationtest.NativeNavigationTest#outgoingTabTapWinsOverSettlingSwipe,dev.craft.navigationtest.NativeNavigationTest#thirdTabTapWinsOverSettlingSwipe,dev.craft.navigationtest.NativeNavigationTest#cancelledSwipeTargetIsVisibleWhenSelectedLater,dev.craft.navigationtest.NativeNavigationTest#completedReverseSwipeKeepsRetainedTabVisible,dev.craft.navigationtest.NativeNavigationTest#nativePullToRefreshSurvivesViewReattachment,dev.craft.navigationtest.NativeNavigationTest#pushedScreenTabAccessoryOpensNativeRouteAndClearsOnBack,dev.craft.navigationtest.NativeFlatListTest#refreshAppearanceUsesTheScreenContrastFallback,dev.craft.navigationtest.NativeNavigationTest#nativeDatePickerKeepsFollowingControlsMounted' || '' }} | |
| 611 | 611 | if: ${{ inputs.scope != 'ios-navigation' && inputs.scope != 'ios-render' }} |
| 612 | 612 | runs-on: ubuntu-latest |
| 613 | 613 | timeout-minutes: 35 |
| @@ -4,6 +4,14 @@ internal class CraftNativeMapView(context: Context) : FrameLayout(context), OnMa | ||
| 4 | 4 | private var map: MapLibreMap? = null |
| 5 | 5 | private var destroyed = false |
| 6 | 6 | private var lifecycleStarted = false |
| 7 | private var lifecycleResumed = false | |
| 8 | private var lifecycleOwner: androidx.lifecycle.LifecycleOwner? = null | |
| 9 | private val lifecycleObserver = object : androidx.lifecycle.DefaultLifecycleObserver { | |
| 10 | override fun onStart(owner: androidx.lifecycle.LifecycleOwner) { startMap() } | |
| 11 | override fun onResume(owner: androidx.lifecycle.LifecycleOwner) { resumeMap() } | |
| 12 | override fun onPause(owner: androidx.lifecycle.LifecycleOwner) { pauseMap() } | |
| 13 | override fun onStop(owner: androidx.lifecycle.LifecycleOwner) { stopMap() } | |
| 14 | } | |
| 7 | 15 | private var pendingProps = JSONObject() |
| 8 | 16 | private var pendingChildren = JSONArray() |
| 9 | 17 | private var styleKey: String? = null |
| @@ -358,14 +366,38 @@ internal class CraftNativeMapView(context: Context) : FrameLayout(context), OnMa | ||
| 358 | 366 | |
| 359 | 367 | override fun onAttachedToWindow() { |
| 360 | 368 | super.onAttachedToWindow() |
| 361 | if (!destroyed && !lifecycleStarted) { mapView.onStart(); mapView.onResume(); lifecycleStarted = true } | |
| 369 | if (destroyed) return | |
| 370 | lifecycleOwner = context as? androidx.lifecycle.LifecycleOwner | |
| 371 | val owner = lifecycleOwner | |
| 372 | if (owner != null) owner.lifecycle.addObserver(lifecycleObserver) | |
| 373 | else { startMap(); resumeMap() } | |
| 362 | 374 | } |
| 363 | 375 | |
| 364 | 376 | override fun onDetachedFromWindow() { |
| 365 | if (lifecycleStarted) { mapView.onPause(); mapView.onStop(); lifecycleStarted = false } | |
| 377 | lifecycleOwner?.lifecycle?.removeObserver(lifecycleObserver) | |
| 378 | lifecycleOwner = null | |
| 379 | stopMap() | |
| 366 | 380 | super.onDetachedFromWindow() |
| 367 | 381 | } |
| 368 | 382 | |
| 383 | private fun startMap() { | |
| 384 | if (!destroyed && !lifecycleStarted) { mapView.onStart(); lifecycleStarted = true } | |
| 385 | } | |
| 386 | ||
| 387 | private fun resumeMap() { | |
| 388 | startMap() | |
| 389 | if (!destroyed && !lifecycleResumed) { mapView.onResume(); lifecycleResumed = true } | |
| 390 | } | |
| 391 | ||
| 392 | private fun pauseMap() { | |
| 393 | if (lifecycleResumed) { mapView.onPause(); lifecycleResumed = false } | |
| 394 | } | |
| 395 | ||
| 396 | private fun stopMap() { | |
| 397 | pauseMap() | |
| 398 | if (lifecycleStarted) { mapView.onStop(); lifecycleStarted = false } | |
| 399 | } | |
| 400 | ||
| 369 | 401 | fun lowMemory() { if (!destroyed) mapView.onLowMemory() } |
| 370 | 402 | |
| 371 | 403 | fun destroy() { |
| @@ -374,7 +406,9 @@ internal class CraftNativeMapView(context: Context) : FrameLayout(context), OnMa | ||
| 374 | 406 | styleVersion++ |
| 375 | 407 | onMarkerTap = null; onMapPress = null; onRegionChangeComplete = null |
| 376 | 408 | markerHandlers.clear(); geometryPoints = emptyList() |
| 377 | if (lifecycleStarted) { mapView.onPause(); mapView.onStop(); lifecycleStarted = false } | |
| 409 | lifecycleOwner?.lifecycle?.removeObserver(lifecycleObserver) | |
| 410 | lifecycleOwner = null | |
| 411 | stopMap() | |
| 378 | 412 | mapView.onDestroy() |
| 379 | 413 | readyStyle = null; map = null |
| 380 | 414 | reportedRegion = null; reportedCamera = null; reportedViewport = null |