From 93428c5cc0779b95d506056d2a39d2028cc3d8b3 Mon Sep 17 00:00:00 2001 From: Abhishek Kejriwal Date: Wed, 21 Dec 2022 10:41:43 -0800 Subject: [PATCH] detect click listener on speed info view --- CHANGELOG.md | 4 ++ libnavui-dropin/api/current.txt | 1 + .../mapbox/navigation/dropin/ClickBehavior.kt | 18 +++++++ .../dropin/infopanel/InfoPanelComponent.kt | 2 +- .../dropin/infopanel/InfoPanelCoordinator.kt | 6 +-- .../dropin/maneuver/ManeuverBehavior.kt | 6 +-- .../maneuver/ManeuverComponentContractImpl.kt | 4 +- .../navigation/dropin/map/MapClickBehavior.kt | 19 ------- .../navigation/dropin/map/MapViewBinder.kt | 2 +- .../map/RouteLineComponentContractImpl.kt | 5 +- .../map/scalebar/ScalebarPlaceholderBinder.kt | 2 +- .../navigationview/NavigationViewBehavior.kt | 14 +++++ .../navigationview/NavigationViewContext.kt | 13 ++--- .../navigationview/NavigationViewListener.kt | 9 ++++ .../NavigationViewListenerRegistry.kt | 23 ++++---- .../dropin/roadname/RoadNameCoordinator.kt | 2 +- .../SpeedInfoComponentContractImpl.kt | 14 +++++ .../dropin/speedlimit/SpeedInfoViewBinder.kt | 3 ++ .../navigation/dropin/ClickBehaviorTest.kt | 42 +++++++++++++++ .../dropin/maneuver/ManeuverBehaviorTest.kt | 2 +- .../ManeuverComponentContractImplTest.kt | 9 ++-- .../dropin/map/MapClickBehaviorTest.kt | 28 ---------- .../NavigationViewListenerRegistryTest.kt | 52 +++++++++---------- .../roadname/RoadNameCoordinatorTest.kt | 2 +- .../speedlimit/internal/SpeedInfoComponent.kt | 21 +++++++- .../ui/speedlimit/view/MapboxSpeedInfoView.kt | 3 ++ .../LoggingNavigationViewListener.kt | 5 ++ 27 files changed, 197 insertions(+), 114 deletions(-) create mode 100644 libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/ClickBehavior.kt delete mode 100644 libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/MapClickBehavior.kt create mode 100644 libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewBehavior.kt create mode 100644 libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/speedlimit/SpeedInfoComponentContractImpl.kt create mode 100644 libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/ClickBehaviorTest.kt delete mode 100644 libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/map/MapClickBehaviorTest.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b58b9de143..bcf15449015 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,10 @@ Mapbox welcomes participation and contributions from everyone. } } ``` +- Added guarantees that route progress with `RouteProgress#currentState == OFF_ROUTE` arrives earlier than `NavigationRerouteController#reroute` is called. [#6764](https://github.com/mapbox/mapbox-navigation-android/pull/6764) +- Fixed a rare `java.lang.NullPointerException: Attempt to read from field 'SpeechAnnouncement PlayCallback.announcement' on a null object reference` crash in `PlayCallback.getAnnouncement`. [#6760](https://github.com/mapbox/mapbox-navigation-android/pull/6760) +- Fixed standalone `MapboxManeuverView` appearance when the app also integrates Drop-In UI. [#6774](https://github.com/mapbox/mapbox-navigation-android/pull/6774) +- Introduced `NavigationViewListener.onSpeedInfoClicked` that would be triggered when `MapboxSpeedInfoView` is clicked upon. [#6770](https://github.com/mapbox/mapbox-navigation-android/pull/6770) ## Mapbox Navigation SDK 2.10.0-rc.1 - 16 December, 2022 ### Changelog diff --git a/libnavui-dropin/api/current.txt b/libnavui-dropin/api/current.txt index 5d377da3182..110117df3b7 100644 --- a/libnavui-dropin/api/current.txt +++ b/libnavui-dropin/api/current.txt @@ -444,6 +444,7 @@ package com.mapbox.navigation.dropin.navigationview { method public void onRouteFetchSuccessful(java.util.List routes); method public void onRouteFetching(long requestId); method public void onRoutePreview(); + method public void onSpeedInfoClicked(com.mapbox.navigation.ui.speedlimit.model.SpeedInfoValue? speedInfo); } } diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/ClickBehavior.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/ClickBehavior.kt new file mode 100644 index 00000000000..840675665dd --- /dev/null +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/ClickBehavior.kt @@ -0,0 +1,18 @@ +package com.mapbox.navigation.dropin + +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.asSharedFlow + +internal class ClickBehavior { + + private val _onViewClicked = MutableSharedFlow( + extraBufferCapacity = 1, + onBufferOverflow = BufferOverflow.DROP_OLDEST, + ) + val onViewClicked = _onViewClicked.asSharedFlow() + + fun onClicked(value: T) { + _onViewClicked.tryEmit(value) + } +} diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/infopanel/InfoPanelComponent.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/infopanel/InfoPanelComponent.kt index f24272a4dc7..6976dae6a40 100644 --- a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/infopanel/InfoPanelComponent.kt +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/infopanel/InfoPanelComponent.kt @@ -23,7 +23,7 @@ internal class InfoPanelComponent( val navigationView = findNavigationView() combine( - context.infoPanelBehavior.slideOffset, + context.behavior.infoPanelBehavior.slideOffset, context.systemBarsInsets ) { slideOffset, insets -> slideOffset to insets diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/infopanel/InfoPanelCoordinator.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/infopanel/InfoPanelCoordinator.kt index 9a0a3000d40..5feeec66f09 100644 --- a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/infopanel/InfoPanelCoordinator.kt +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/infopanel/InfoPanelCoordinator.kt @@ -35,12 +35,12 @@ internal class InfoPanelCoordinator( private val updateGuideline = object : BottomSheetBehavior.BottomSheetCallback() { override fun onStateChanged(bottomSheet: View, newState: Int) { - context.infoPanelBehavior.updateBottomSheetState(newState) + context.behavior.infoPanelBehavior.updateBottomSheetState(newState) updateGuidelinePosition() } override fun onSlide(bottomSheet: View, slideOffset: Float) { - context.infoPanelBehavior.updateSlideOffset(slideOffset) + context.behavior.infoPanelBehavior.updateSlideOffset(slideOffset) updateGuidelinePosition() } } @@ -184,7 +184,7 @@ internal class InfoPanelCoordinator( BottomSheetBehavior.STATE_HIDDEN -> -1.0f else -> null }?.also { slideOffset -> - context.infoPanelBehavior.updateSlideOffset(slideOffset) + context.behavior.infoPanelBehavior.updateSlideOffset(slideOffset) } } } diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/maneuver/ManeuverBehavior.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/maneuver/ManeuverBehavior.kt index d51bed1b234..659769729f1 100644 --- a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/maneuver/ManeuverBehavior.kt +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/maneuver/ManeuverBehavior.kt @@ -6,16 +6,16 @@ import kotlinx.coroutines.flow.asStateFlow internal class ManeuverBehavior { - private val _maneuverBehavior = MutableStateFlow( + private val _maneuverViewState = MutableStateFlow( MapboxManeuverViewState.COLLAPSED ) private val _maneuverViewVisibility = MutableStateFlow(false) - val maneuverBehavior = _maneuverBehavior.asStateFlow() + val maneuverViewState = _maneuverViewState.asStateFlow() val maneuverViewVisibility = _maneuverViewVisibility.asStateFlow() fun updateBehavior(newState: MapboxManeuverViewState) { - _maneuverBehavior.value = newState + _maneuverViewState.value = newState } fun updateViewVisibility(visibility: Boolean) { diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/maneuver/ManeuverComponentContractImpl.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/maneuver/ManeuverComponentContractImpl.kt index 3589f578385..a32422f6200 100644 --- a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/maneuver/ManeuverComponentContractImpl.kt +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/maneuver/ManeuverComponentContractImpl.kt @@ -9,10 +9,10 @@ internal class ManeuverComponentContractImpl( ) : ManeuverComponentContract { override fun onManeuverViewStateChanged(state: MapboxManeuverViewState) { - context.maneuverBehavior.updateBehavior(state) + context.behavior.maneuverBehavior.updateBehavior(state) } override fun onManeuverViewVisibilityChanged(isVisible: Boolean) { - context.maneuverBehavior.updateViewVisibility(isVisible) + context.behavior.maneuverBehavior.updateViewVisibility(isVisible) } } diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/MapClickBehavior.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/MapClickBehavior.kt deleted file mode 100644 index 7d79afd33d2..00000000000 --- a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/MapClickBehavior.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.mapbox.navigation.dropin.map - -import com.mapbox.geojson.Point -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.asSharedFlow - -internal class MapClickBehavior { - - private val _mapClickBehavior = MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST, - ) - val mapClickBehavior = _mapClickBehavior.asSharedFlow() - - fun onMapClicked(point: Point) { - _mapClickBehavior.tryEmit(point) - } -} diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/MapViewBinder.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/MapViewBinder.kt index 699c767dfdc..60d574ec105 100644 --- a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/MapViewBinder.kt +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/MapViewBinder.kt @@ -108,7 +108,7 @@ abstract class MapViewBinder : UIBinder { private fun routeLineComponent(lineOptions: MapboxRouteLineOptions, mapView: MapView) = RouteLineComponent(mapView.getMapboxMap(), mapView, lineOptions, contractProvider = { - RouteLineComponentContractImpl(context.store, context.mapClickBehavior) + RouteLineComponentContractImpl(context.store, context.behavior.mapClickBehavior) }) private fun longPressMapComponent(navigationState: NavigationState, mapView: MapView) = diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/RouteLineComponentContractImpl.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/RouteLineComponentContractImpl.kt index 787db0d710f..a6c132ddbc9 100644 --- a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/RouteLineComponentContractImpl.kt +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/RouteLineComponentContractImpl.kt @@ -3,6 +3,7 @@ package com.mapbox.navigation.dropin.map import com.mapbox.geojson.Point import com.mapbox.navigation.base.route.NavigationRoute import com.mapbox.navigation.core.MapboxNavigation +import com.mapbox.navigation.dropin.ClickBehavior import com.mapbox.navigation.ui.app.internal.Store import com.mapbox.navigation.ui.app.internal.navigation.NavigationState import com.mapbox.navigation.ui.app.internal.routefetch.RoutePreviewAction @@ -14,7 +15,7 @@ import kotlinx.coroutines.flow.combine internal class RouteLineComponentContractImpl( private val store: Store, - private val mapClickBehavior: MapClickBehavior, + private val mapClickBehavior: ClickBehavior, ) : RouteLineComponentContract { override fun setRoutes(mapboxNavigation: MapboxNavigation, routes: List) { when (store.state.value.navigation) { @@ -48,6 +49,6 @@ internal class RouteLineComponentContractImpl( } override fun onMapClicked(point: Point) { - mapClickBehavior.onMapClicked(point) + mapClickBehavior.onClicked(point) } } diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/scalebar/ScalebarPlaceholderBinder.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/scalebar/ScalebarPlaceholderBinder.kt index 1cc7ab8b465..25565deb141 100644 --- a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/scalebar/ScalebarPlaceholderBinder.kt +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/map/scalebar/ScalebarPlaceholderBinder.kt @@ -17,7 +17,7 @@ internal class ScalebarPlaceholderBinder( return ScalebarPlaceholderComponent( binding.scalebarPlaceholder, context.options.showMapScalebar, - context.maneuverBehavior.maneuverViewVisibility + context.behavior.maneuverBehavior.maneuverViewVisibility ) } diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewBehavior.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewBehavior.kt new file mode 100644 index 00000000000..cf4ef99f48c --- /dev/null +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewBehavior.kt @@ -0,0 +1,14 @@ +package com.mapbox.navigation.dropin.navigationview + +import com.mapbox.geojson.Point +import com.mapbox.navigation.dropin.ClickBehavior +import com.mapbox.navigation.dropin.infopanel.InfoPanelBehavior +import com.mapbox.navigation.dropin.maneuver.ManeuverBehavior +import com.mapbox.navigation.ui.speedlimit.model.SpeedInfoValue + +internal class NavigationViewBehavior { + val maneuverBehavior = ManeuverBehavior() + val infoPanelBehavior = InfoPanelBehavior() + val mapClickBehavior = ClickBehavior() + val speedInfoBehavior = ClickBehavior() +} diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewContext.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewContext.kt index 280ac61709d..4d6283133f8 100644 --- a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewContext.kt +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewContext.kt @@ -8,9 +8,6 @@ import com.mapbox.navigation.dropin.NavigationView import com.mapbox.navigation.dropin.ViewBinderCustomization import com.mapbox.navigation.dropin.ViewOptionsCustomization import com.mapbox.navigation.dropin.ViewStyleCustomization -import com.mapbox.navigation.dropin.infopanel.InfoPanelBehavior -import com.mapbox.navigation.dropin.maneuver.ManeuverBehavior -import com.mapbox.navigation.dropin.map.MapClickBehavior import com.mapbox.navigation.dropin.map.MapStyleLoader import com.mapbox.navigation.dropin.map.MapViewOwner import com.mapbox.navigation.dropin.map.marker.MapMarkerFactory @@ -45,17 +42,15 @@ internal class NavigationViewContext( val uiBinders = NavigationViewBinder() val styles = NavigationViewStyles(context) val options = NavigationViewOptions(context) - val maneuverBehavior = ManeuverBehavior() - val infoPanelBehavior = InfoPanelBehavior() val mapViewOwner = MapViewOwner() val mapStyleLoader = MapStyleLoader(context, options) - val mapClickBehavior = MapClickBehavior() + val behavior by lazy { + NavigationViewBehavior() + } val listenerRegistry by lazy { NavigationViewListenerRegistry( store, - maneuverBehavior, - infoPanelBehavior, - mapClickBehavior, + behavior, lifecycleOwner.lifecycleScope ) } diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewListener.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewListener.kt index 909e649f73c..d759d9f95fb 100644 --- a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewListener.kt +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewListener.kt @@ -9,6 +9,8 @@ import com.mapbox.navigation.base.route.Router import com.mapbox.navigation.base.route.RouterFailure import com.mapbox.navigation.base.route.RouterOrigin import com.mapbox.navigation.dropin.NavigationView +import com.mapbox.navigation.ui.speedlimit.model.SpeedInfoValue +import com.mapbox.navigation.ui.speedlimit.view.MapboxSpeedInfoView /** * Interface definition for the NavigationView listener. @@ -159,4 +161,11 @@ abstract class NavigationViewListener { * @param point The projected map coordinate the user clicked on. */ open fun onMapClicked(point: Point) = Unit + + /** + * Called when [MapboxSpeedInfoView] was clicked + * + * @param speedInfo [SpeedInfoValue] at the time user clicked on the view. + */ + open fun onSpeedInfoClicked(speedInfo: SpeedInfoValue?) = Unit } diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewListenerRegistry.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewListenerRegistry.kt index 492682f42d3..9bfa20f4563 100644 --- a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewListenerRegistry.kt +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/navigationview/NavigationViewListenerRegistry.kt @@ -2,9 +2,6 @@ package com.mapbox.navigation.dropin.navigationview import androidx.annotation.VisibleForTesting import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.mapbox.navigation.dropin.infopanel.InfoPanelBehavior -import com.mapbox.navigation.dropin.maneuver.ManeuverBehavior -import com.mapbox.navigation.dropin.map.MapClickBehavior import com.mapbox.navigation.ui.app.internal.Store import com.mapbox.navigation.ui.app.internal.camera.TargetCameraMode import com.mapbox.navigation.ui.app.internal.navigation.NavigationState @@ -20,10 +17,8 @@ import kotlinx.coroutines.launch internal class NavigationViewListenerRegistry( private val store: Store, - private val maneuverSubscriber: ManeuverBehavior, - private val infoPanelSubscriber: InfoPanelBehavior, - private val mapClickSubscriber: MapClickBehavior, - private val coroutineScope: CoroutineScope + private val behavior: NavigationViewBehavior, + private val coroutineScope: CoroutineScope, ) { private var listeners = mutableMapOf() @@ -93,7 +88,8 @@ internal class NavigationViewListenerRegistry( } } launch { - infoPanelSubscriber + behavior + .infoPanelBehavior .bottomSheetState .filterNotNull() .collect { behavior -> @@ -107,11 +103,12 @@ internal class NavigationViewListenerRegistry( } } launch { - infoPanelSubscriber.slideOffset.collect(listener::onInfoPanelSlide) + behavior.infoPanelBehavior.slideOffset.collect(listener::onInfoPanelSlide) } launch { - maneuverSubscriber + behavior .maneuverBehavior + .maneuverViewState .collect { behavior -> when (behavior) { MapboxManeuverViewState.EXPANDED -> { @@ -124,9 +121,13 @@ internal class NavigationViewListenerRegistry( } } - mapClickSubscriber.mapClickBehavior + behavior.mapClickBehavior.onViewClicked .onEach { listener.onMapClicked(it) } .launchIn(scope = this) + + behavior.speedInfoBehavior.onViewClicked + .onEach { listener.onSpeedInfoClicked(it) } + .launchIn(scope = this) } } diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/roadname/RoadNameCoordinator.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/roadname/RoadNameCoordinator.kt index f5484bfac07..4697123ba35 100644 --- a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/roadname/RoadNameCoordinator.kt +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/roadname/RoadNameCoordinator.kt @@ -30,7 +30,7 @@ internal class RoadNameCoordinator( super.onAttached(mapboxNavigation) coroutineScope.launch { - context.infoPanelBehavior.bottomSheetState + context.behavior.infoPanelBehavior.bottomSheetState .filterNotNull() .map { bottomSheetState -> val isBottomSheetVisible = bottomSheetState != BottomSheetBehavior.STATE_HIDDEN diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/speedlimit/SpeedInfoComponentContractImpl.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/speedlimit/SpeedInfoComponentContractImpl.kt new file mode 100644 index 00000000000..85f1faa913c --- /dev/null +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/speedlimit/SpeedInfoComponentContractImpl.kt @@ -0,0 +1,14 @@ +package com.mapbox.navigation.dropin.speedlimit + +import com.mapbox.navigation.dropin.ClickBehavior +import com.mapbox.navigation.ui.speedlimit.internal.SpeedInfoComponentContract +import com.mapbox.navigation.ui.speedlimit.model.SpeedInfoValue + +internal class SpeedInfoComponentContractImpl( + private val speedInfoBehavior: ClickBehavior +) : SpeedInfoComponentContract { + + override fun onSpeedInfoClicked(speedInfo: SpeedInfoValue?) { + speedInfoBehavior.onClicked(speedInfo) + } +} diff --git a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/speedlimit/SpeedInfoViewBinder.kt b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/speedlimit/SpeedInfoViewBinder.kt index a3b84ca7406..36799fad245 100644 --- a/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/speedlimit/SpeedInfoViewBinder.kt +++ b/libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/speedlimit/SpeedInfoViewBinder.kt @@ -32,6 +32,9 @@ internal class SpeedInfoViewBinder( speedInfoOptions = options, speedInfoView = binding.speedInfoView, distanceFormatterOptions = distanceFormatter, + contractProvider = { + SpeedInfoComponentContractImpl(context.behavior.speedInfoBehavior) + } ) } } diff --git a/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/ClickBehaviorTest.kt b/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/ClickBehaviorTest.kt new file mode 100644 index 00000000000..74b3600cbfc --- /dev/null +++ b/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/ClickBehaviorTest.kt @@ -0,0 +1,42 @@ +package com.mapbox.navigation.dropin + +import com.mapbox.geojson.Point +import com.mapbox.navigation.ui.speedlimit.model.SpeedInfoValue +import io.mockk.mockk +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.cancelAndJoin +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.test.runBlockingTest +import org.junit.Assert.assertEquals +import org.junit.Test + +@ExperimentalCoroutinesApi +class ClickBehaviorTest { + + @Test + fun `when speed info is clicked, event is received`() = runBlockingTest { + val sut = ClickBehavior() + val events = arrayListOf() + val job = sut.onViewClicked.onEach { events.add(it) }.launchIn(scope = this) + + val speedInfo = mockk() + sut.onClicked(speedInfo) + job.cancelAndJoin() + + assertEquals(listOf(speedInfo), events) + } + + @Test + fun `when map is clicked, event is received`() = runBlockingTest { + val sut = ClickBehavior() + val events = arrayListOf() + val job = sut.onViewClicked.onEach { events.add(it) }.launchIn(scope = this) + + val point = mockk() + sut.onClicked(point) + job.cancelAndJoin() + + assertEquals(listOf(point), events) + } +} diff --git a/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/maneuver/ManeuverBehaviorTest.kt b/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/maneuver/ManeuverBehaviorTest.kt index 7b7c5169d11..bdcc1c72cb6 100644 --- a/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/maneuver/ManeuverBehaviorTest.kt +++ b/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/maneuver/ManeuverBehaviorTest.kt @@ -12,7 +12,7 @@ class ManeuverBehaviorTest { sut.updateBehavior(MapboxManeuverViewState.EXPANDED) - assertEquals(MapboxManeuverViewState.EXPANDED, sut.maneuverBehavior.value) + assertEquals(MapboxManeuverViewState.EXPANDED, sut.maneuverViewState.value) } @Test diff --git a/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/maneuver/ManeuverComponentContractImplTest.kt b/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/maneuver/ManeuverComponentContractImplTest.kt index bec758f88f8..924b1b6897b 100644 --- a/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/maneuver/ManeuverComponentContractImplTest.kt +++ b/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/maneuver/ManeuverComponentContractImplTest.kt @@ -12,7 +12,7 @@ import org.junit.Test class ManeuverComponentContractImplTest { private val navigationViewContext: NavigationViewContext = mockk(relaxed = true) { - every { maneuverBehavior.updateBehavior(any()) } just Runs + every { behavior.maneuverBehavior.updateBehavior(any()) } just Runs } private val sut = ManeuverComponentContractImpl(navigationViewContext) @@ -21,7 +21,10 @@ class ManeuverComponentContractImplTest { sut.onManeuverViewStateChanged(MapboxManeuverViewState.EXPANDED) verify { - navigationViewContext.maneuverBehavior.updateBehavior(MapboxManeuverViewState.EXPANDED) + navigationViewContext + .behavior + .maneuverBehavior + .updateBehavior(MapboxManeuverViewState.EXPANDED) } } @@ -30,7 +33,7 @@ class ManeuverComponentContractImplTest { sut.onManeuverViewVisibilityChanged(true) verify { - navigationViewContext.maneuverBehavior.updateViewVisibility(true) + navigationViewContext.behavior.maneuverBehavior.updateViewVisibility(true) } } } diff --git a/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/map/MapClickBehaviorTest.kt b/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/map/MapClickBehaviorTest.kt deleted file mode 100644 index 08e3d6a21fa..00000000000 --- a/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/map/MapClickBehaviorTest.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.mapbox.navigation.dropin.map - -import com.mapbox.geojson.Point -import io.mockk.mockk -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.cancelAndJoin -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.test.runBlockingTest -import org.junit.Assert.assertEquals -import org.junit.Test - -@ExperimentalCoroutinesApi -class MapClickBehaviorTest { - - @Test - fun `when map is clicked, event is received`() = runBlockingTest { - val sut = MapClickBehavior() - val events = arrayListOf() - val job = sut.mapClickBehavior.onEach { events.add(it) }.launchIn(scope = this) - - val point = mockk() - sut.onMapClicked(point) - job.cancelAndJoin() - - assertEquals(listOf(point), events) - } -} diff --git a/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/navigationview/NavigationViewListenerRegistryTest.kt b/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/navigationview/NavigationViewListenerRegistryTest.kt index 2cc93995d2b..b74dd4a370b 100644 --- a/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/navigationview/NavigationViewListenerRegistryTest.kt +++ b/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/navigationview/NavigationViewListenerRegistryTest.kt @@ -7,9 +7,6 @@ import com.mapbox.maps.EdgeInsets import com.mapbox.navigation.base.route.NavigationRoute import com.mapbox.navigation.base.route.RouterFailure import com.mapbox.navigation.base.route.RouterOrigin -import com.mapbox.navigation.dropin.infopanel.InfoPanelBehavior -import com.mapbox.navigation.dropin.maneuver.ManeuverBehavior -import com.mapbox.navigation.dropin.map.MapClickBehavior import com.mapbox.navigation.dropin.util.TestStore import com.mapbox.navigation.testing.MainCoroutineRule import com.mapbox.navigation.ui.app.internal.State @@ -18,14 +15,13 @@ import com.mapbox.navigation.ui.app.internal.destination.Destination import com.mapbox.navigation.ui.app.internal.navigation.NavigationState import com.mapbox.navigation.ui.app.internal.routefetch.RoutePreviewState import com.mapbox.navigation.ui.maneuver.view.MapboxManeuverViewState -import io.mockk.every +import com.mapbox.navigation.ui.speedlimit.model.SpeedInfoValue import io.mockk.mockk import io.mockk.spyk import io.mockk.verify import io.mockk.verifyOrder import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow import org.junit.Before import org.junit.Rule import org.junit.Test @@ -38,29 +34,22 @@ class NavigationViewListenerRegistryTest { private lateinit var sut: NavigationViewListenerRegistry private lateinit var testStore: TestStore - private lateinit var maneuverBehaviorFlow: MutableStateFlow - private lateinit var infoPanelBehavior: InfoPanelBehavior - private lateinit var mapClickBehavior: MapClickBehavior + private lateinit var navigationViewBehavior: NavigationViewBehavior private lateinit var testListener: NavigationViewListener private lateinit var slideOffsetFlow: MutableStateFlow @Before fun setUp() { testStore = TestStore() - infoPanelBehavior = InfoPanelBehavior() - mapClickBehavior = MapClickBehavior() - maneuverBehaviorFlow = MutableStateFlow(MapboxManeuverViewState.COLLAPSED) + navigationViewBehavior = NavigationViewBehavior() + slideOffsetFlow = MutableStateFlow(-1f) - val mockManeuverBehavior = mockk { - every { maneuverBehavior } returns maneuverBehaviorFlow.asStateFlow() - } + testListener = spyk(object : NavigationViewListener() {}) sut = NavigationViewListenerRegistry( testStore, - mockManeuverBehavior, - infoPanelBehavior, - mapClickBehavior, + navigationViewBehavior, coroutineRule.coroutineScope ) } @@ -251,7 +240,7 @@ class NavigationViewListenerRegistryTest { sut.registerListener(testListener) val newState = BottomSheetBehavior.STATE_HIDDEN - infoPanelBehavior.updateBottomSheetState(newState) + navigationViewBehavior.infoPanelBehavior.updateBottomSheetState(newState) verify { testListener.onInfoPanelHidden() @@ -263,7 +252,7 @@ class NavigationViewListenerRegistryTest { sut.registerListener(testListener) val newState = BottomSheetBehavior.STATE_EXPANDED - infoPanelBehavior.updateBottomSheetState(newState) + navigationViewBehavior.infoPanelBehavior.updateBottomSheetState(newState) verify { testListener.onInfoPanelExpanded() @@ -275,7 +264,7 @@ class NavigationViewListenerRegistryTest { sut.registerListener(testListener) val newState = BottomSheetBehavior.STATE_COLLAPSED - infoPanelBehavior.updateBottomSheetState(newState) + navigationViewBehavior.infoPanelBehavior.updateBottomSheetState(newState) verify { testListener.onInfoPanelCollapsed() @@ -287,7 +276,7 @@ class NavigationViewListenerRegistryTest { sut.registerListener(testListener) val newState = BottomSheetBehavior.STATE_DRAGGING - infoPanelBehavior.updateBottomSheetState(newState) + navigationViewBehavior.infoPanelBehavior.updateBottomSheetState(newState) verify { testListener.onInfoPanelDragging() @@ -299,7 +288,7 @@ class NavigationViewListenerRegistryTest { sut.registerListener(testListener) val newState = BottomSheetBehavior.STATE_SETTLING - infoPanelBehavior.updateBottomSheetState(newState) + navigationViewBehavior.infoPanelBehavior.updateBottomSheetState(newState) verify { testListener.onInfoPanelSettling() @@ -321,7 +310,7 @@ class NavigationViewListenerRegistryTest { sut.registerListener(testListener) val newState = MapboxManeuverViewState.EXPANDED - maneuverBehaviorFlow.value = newState + navigationViewBehavior.maneuverBehavior.updateBehavior(newState) verify { testListener.onManeuverExpanded() @@ -332,9 +321,9 @@ class NavigationViewListenerRegistryTest { fun onManeuverCollapsed() { sut.registerListener(testListener) val expanded = MapboxManeuverViewState.EXPANDED - maneuverBehaviorFlow.value = expanded + navigationViewBehavior.maneuverBehavior.updateBehavior(expanded) val collapsed = MapboxManeuverViewState.COLLAPSED - maneuverBehaviorFlow.value = collapsed + navigationViewBehavior.maneuverBehavior.updateBehavior(collapsed) verify { testListener.onManeuverCollapsed() @@ -345,7 +334,7 @@ class NavigationViewListenerRegistryTest { fun onMapClicked() { sut.registerListener(testListener) val point = mockk() - mapClickBehavior.onMapClicked(point) + navigationViewBehavior.mapClickBehavior.onClicked(point) verify { testListener.onMapClicked(point) } } @@ -354,10 +343,19 @@ class NavigationViewListenerRegistryTest { fun onInfoPanelSlide() { sut.registerListener(testListener) - infoPanelBehavior.updateSlideOffset(0.6f) + navigationViewBehavior.infoPanelBehavior.updateSlideOffset(0.6f) verify { testListener.onInfoPanelSlide(0.6f) } } + + @Test + fun onSpeedInfoClicked() { + sut.registerListener(testListener) + val speedInfo = mockk() + navigationViewBehavior.speedInfoBehavior.onClicked(speedInfo) + + verify { testListener.onSpeedInfoClicked(speedInfo) } + } } diff --git a/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/roadname/RoadNameCoordinatorTest.kt b/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/roadname/RoadNameCoordinatorTest.kt index 3f8c2fbf152..d4278d85cab 100644 --- a/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/roadname/RoadNameCoordinatorTest.kt +++ b/libnavui-dropin/src/test/java/com/mapbox/navigation/dropin/roadname/RoadNameCoordinatorTest.kt @@ -52,7 +52,7 @@ class RoadNameCoordinatorTest { } } private val context = mockk(relaxed = true) { - every { infoPanelBehavior } returns mockk { + every { behavior.infoPanelBehavior } returns mockk { every { bottomSheetState } returns bottomSheetFlow } every { uiBinders } returns mockk { diff --git a/libnavui-speedlimit/src/main/java/com/mapbox/navigation/ui/speedlimit/internal/SpeedInfoComponent.kt b/libnavui-speedlimit/src/main/java/com/mapbox/navigation/ui/speedlimit/internal/SpeedInfoComponent.kt index 4b75e239cc6..85f83d4b437 100644 --- a/libnavui-speedlimit/src/main/java/com/mapbox/navigation/ui/speedlimit/internal/SpeedInfoComponent.kt +++ b/libnavui-speedlimit/src/main/java/com/mapbox/navigation/ui/speedlimit/internal/SpeedInfoComponent.kt @@ -6,15 +6,30 @@ import com.mapbox.navigation.core.internal.extensions.flowLocationMatcherResult import com.mapbox.navigation.ui.base.lifecycle.UIComponent import com.mapbox.navigation.ui.speedlimit.api.MapboxSpeedInfoApi import com.mapbox.navigation.ui.speedlimit.model.MapboxSpeedInfoOptions +import com.mapbox.navigation.ui.speedlimit.model.SpeedInfoValue import com.mapbox.navigation.ui.speedlimit.view.MapboxSpeedInfoView +import com.mapbox.navigation.ui.utils.internal.Provider import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch +interface SpeedInfoComponentContract { + fun onSpeedInfoClicked(speedInfo: SpeedInfoValue?) +} + +internal class MapboxSpeedInfoComponentContract : SpeedInfoComponentContract { + override fun onSpeedInfoClicked(speedInfo: SpeedInfoValue?) { + // do nothing + } +} + class SpeedInfoComponent( private val speedInfoView: MapboxSpeedInfoView, private val speedInfoOptions: MapboxSpeedInfoOptions, private val distanceFormatterOptions: DistanceFormatterOptions, - private val speedInfoApi: MapboxSpeedInfoApi = MapboxSpeedInfoApi() + private val speedInfoApi: MapboxSpeedInfoApi = MapboxSpeedInfoApi(), + private val contractProvider: Provider = Provider { + MapboxSpeedInfoComponentContract() + } ) : UIComponent() { override fun onAttached(mapboxNavigation: MapboxNavigation) { @@ -22,6 +37,10 @@ class SpeedInfoComponent( speedInfoView.applyOptions(speedInfoOptions) + speedInfoView.setOnClickListener { + contractProvider.get().onSpeedInfoClicked(speedInfoView.speedInfo) + } + coroutineScope.launch { mapboxNavigation.flowLocationMatcherResult().collect { locationMatcher -> val value = speedInfoApi.updatePostedAndCurrentSpeed( diff --git a/libnavui-speedlimit/src/main/java/com/mapbox/navigation/ui/speedlimit/view/MapboxSpeedInfoView.kt b/libnavui-speedlimit/src/main/java/com/mapbox/navigation/ui/speedlimit/view/MapboxSpeedInfoView.kt index 674f1da0a27..4b790864d8e 100644 --- a/libnavui-speedlimit/src/main/java/com/mapbox/navigation/ui/speedlimit/view/MapboxSpeedInfoView.kt +++ b/libnavui-speedlimit/src/main/java/com/mapbox/navigation/ui/speedlimit/view/MapboxSpeedInfoView.kt @@ -121,6 +121,8 @@ class MapboxSpeedInfoView : FrameLayout { */ val speedInfoCurrentSpeedVienna: AppCompatTextView = binding.currentSpeedVienna + internal var speedInfo: SpeedInfoValue? = null + init { applyOptions(speedInfoOptions) updateStyles() @@ -132,6 +134,7 @@ class MapboxSpeedInfoView : FrameLayout { * @param speedInfo SpeedInfoValue */ fun render(speedInfo: SpeedInfoValue) { + this.speedInfo = speedInfo renderSpeedUnit(speedInfo.postedSpeedUnit) if (speedInfo.postedSpeed != null) { showMutcdOrVienna(speedInfo.speedSignConvention) diff --git a/qa-test-app/src/main/java/com/mapbox/navigation/qa_test_app/view/customnavview/LoggingNavigationViewListener.kt b/qa-test-app/src/main/java/com/mapbox/navigation/qa_test_app/view/customnavview/LoggingNavigationViewListener.kt index 50166a35424..e92bcfccc9e 100644 --- a/qa-test-app/src/main/java/com/mapbox/navigation/qa_test_app/view/customnavview/LoggingNavigationViewListener.kt +++ b/qa-test-app/src/main/java/com/mapbox/navigation/qa_test_app/view/customnavview/LoggingNavigationViewListener.kt @@ -8,6 +8,7 @@ import com.mapbox.navigation.base.route.NavigationRoute import com.mapbox.navigation.base.route.RouterFailure import com.mapbox.navigation.base.route.RouterOrigin import com.mapbox.navigation.dropin.navigationview.NavigationViewListener +import com.mapbox.navigation.ui.speedlimit.model.SpeedInfoValue import com.mapbox.navigation.utils.internal.logD @OptIn(ExperimentalPreviewMapboxNavigationAPI::class) @@ -110,6 +111,10 @@ class LoggingNavigationViewListener( log("listener onMapClicked point = $point") } + override fun onSpeedInfoClicked(speedInfo: SpeedInfoValue?) { + log("listener onSpeedInfoClicked speedInfo = $speedInfo") + } + private fun log(message: String) { logD(message, tag) }