@@ -90,6 +90,7 @@ public class CarPlayManager: NSObject {
9090
9191 private weak var navigationService : NavigationService ?
9292 private var idleTimerCancellable : IdleTimerManager . Cancellable ?
93+ private var indexedRouteResponse : IndexedRouteResponse ?
9394
9495 /**
9596 Programatically begins a CarPlay turn-by-turn navigation session.
@@ -493,8 +494,7 @@ extension CarPlayManager: CPInterfaceControllerDelegate {
493494 carPlayMapViewController. recenterButton. isHidden = true
494495 }
495496
496- if let userInfo = template. userInfo as? Dictionary < String , Any > ,
497- let currentActivity = userInfo [ CarPlayManager . currentActivityKey] as? CarPlayActivity {
497+ if let currentActivity = template. currentActivity {
498498 self . currentActivity = currentActivity
499499 } else {
500500 self . currentActivity = nil
@@ -505,13 +505,8 @@ extension CarPlayManager: CPInterfaceControllerDelegate {
505505 delegate? . carPlayManager ( self , templateDidAppear: template, animated: animated)
506506
507507 guard interfaceController? . topTemplate == mainMapTemplate,
508- template == interfaceController? . rootTemplate,
509- let carPlayMapViewController = carPlayMapViewController else { return }
510-
511- let navigationMapView = carPlayMapViewController. navigationMapView
512- navigationMapView. removeRoutes ( )
513- navigationMapView. removeContinuousAlternativesRoutes ( )
514- navigationMapView. removeWaypoints ( )
508+ template == interfaceController? . rootTemplate else { return }
509+ self . removeRoutesFromMap ( )
515510 }
516511
517512 public func templateWillDisappear( _ template: CPTemplate , animated: Bool ) {
@@ -521,7 +516,7 @@ extension CarPlayManager: CPInterfaceControllerDelegate {
521516 let topTemplate = interfaceController. topTemplate,
522517 type ( of: topTemplate) == CPSearchTemplate . self ||
523518 interfaceController. templates. count == 1 else { return }
524-
519+
525520 navigationMapView? . navigationCamera. follow ( )
526521 }
527522
@@ -614,10 +609,27 @@ extension CarPlayManager {
614609 previewed.
615610 */
616611 public func previewRoutes( for indexedRouteResponse: IndexedRouteResponse ) {
612+ guard shouldPreviewRoutes ( for: indexedRouteResponse) else { return }
617613 let trip = CPTrip ( indexedRouteResponse: indexedRouteResponse)
618614 previewRoutes ( for: trip)
619615 }
620616
617+ /**
618+ Allows to cancel routes preview on CarPlay .
619+ */
620+ public func cancelRoutesPreview( ) {
621+ guard self . indexedRouteResponse != nil else { return }
622+ self . indexedRouteResponse = nil
623+ mainMapTemplate? . hideTripPreviews ( )
624+ popToRootTemplate ( interfaceController: interfaceController, animated: true )
625+ delegate? . carPlayManagerDidCancelPreview ( self )
626+ }
627+
628+ func shouldPreviewRoutes( for indexedRouteResponse: IndexedRouteResponse ) -> Bool {
629+ guard self . indexedRouteResponse? . currentRoute == indexedRouteResponse. currentRoute else { return true }
630+ return self . indexedRouteResponse? . routeResponse. routes != indexedRouteResponse. routeResponse. routes
631+ }
632+
621633 func previewRoutes( for trip: CPTrip ) {
622634 guard let traitCollection = ( self . carWindow? . rootViewController as? CarPlayMapViewController ) ? . traitCollection,
623635 let interfaceController = interfaceController else {
@@ -635,8 +647,23 @@ extension CarPlayManager {
635647 previewText = customPreviewText
636648 }
637649
650+ previewMapTemplate. backButton = defaultTripPreviewBackButton ( )
638651 previewMapTemplate. showTripPreviews ( [ modifiedTrip] , textConfiguration: previewText)
639- interfaceController. pushTemplate ( previewMapTemplate, animated: true )
652+
653+ if currentActivity == . previewing {
654+ interfaceController. popTemplate ( animated: false )
655+ interfaceController. pushTemplate ( previewMapTemplate, animated: false )
656+ } else {
657+ interfaceController. pushTemplate ( previewMapTemplate, animated: true )
658+ }
659+ }
660+
661+ func removeRoutesFromMap( ) {
662+ indexedRouteResponse = nil
663+ guard let navigationMapView = carPlayMapViewController? . navigationMapView else { return }
664+ navigationMapView. removeRoutes ( )
665+ navigationMapView. removeContinuousAlternativesRoutes ( )
666+ navigationMapView. removeWaypoints ( )
640667 }
641668
642669 func calculate( _ options: RouteOptions , completionHandler: @escaping RoutingProvider . IndexedRouteResponseCompletionHandler ) {
@@ -690,6 +717,18 @@ extension CarPlayManager {
690717 overviewButtonTitle: overviewTitle)
691718 return defaultPreviewText
692719 }
720+
721+ private func defaultTripPreviewBackButton( ) -> CPBarButton {
722+ let backButton = CPBarButton ( type: . text) { [ weak self] ( button: CPBarButton ) in
723+ guard let self = self else { return }
724+ self . cancelRoutesPreview ( )
725+ }
726+ backButton. title = NSLocalizedString ( " CARPLAY_PREVIEW_BACK " ,
727+ bundle: . mapboxNavigation,
728+ value: " BACK " ,
729+ comment: " Title for trip preview back button " )
730+ return backButton
731+ }
693732}
694733
695734// MARK: CPMapTemplateDelegate Methods
@@ -704,7 +743,7 @@ extension CarPlayManager: CPMapTemplateDelegate {
704743 return
705744 }
706745
707- guard let indexedRouteResponse = routeChoice. indexedRouteResponseUserInfo ? . indexedRouteResponse else {
746+ guard let indexedRouteResponse = routeChoice. indexedRouteResponse else {
708747 preconditionFailure ( " CPRouteChoice should contain `IndexedRouteResponseUserInfo` struct. " )
709748 }
710749
@@ -759,10 +798,7 @@ extension CarPlayManager: CPMapTemplateDelegate {
759798 self . delegate? . carPlayManager ( self , didPresent: carPlayNavigationViewController)
760799 }
761800
762- let navigationMapView = carPlayMapViewController. navigationMapView
763- navigationMapView. removeRoutes ( )
764- navigationMapView. removeContinuousAlternativesRoutes ( )
765- navigationMapView. removeWaypoints ( )
801+ self . removeRoutesFromMap ( )
766802 }
767803
768804 func navigationMapTemplate( ) -> CPMapTemplate {
@@ -784,7 +820,7 @@ extension CarPlayManager: CPMapTemplateDelegate {
784820 using routeChoice: CPRouteChoice ) {
785821 guard let carPlayMapViewController = carPlayMapViewController else { return }
786822
787- guard let indexedRouteResponse = routeChoice. indexedRouteResponseUserInfo ? . indexedRouteResponse,
823+ guard let indexedRouteResponse = routeChoice. indexedRouteResponse,
788824 let route = indexedRouteResponse. currentRoute,
789825 var routes = indexedRouteResponse. routeResponse. routes else {
790826 preconditionFailure ( " CPRouteChoice should contain `IndexedRouteResponseUserInfo` struct. " )
@@ -803,7 +839,7 @@ extension CarPlayManager: CPMapTemplateDelegate {
803839 navigationMapView. showcase ( routes,
804840 routesPresentationStyle: . all( shouldFit: true , cameraOptions: cameraOptions) ,
805841 animated: true )
806-
842+ self . indexedRouteResponse = indexedRouteResponse
807843 delegate? . carPlayManager ( self , selectedPreviewFor: trip, using: routeChoice)
808844 }
809845
@@ -812,9 +848,7 @@ extension CarPlayManager: CPMapTemplateDelegate {
812848 return
813849 }
814850 let navigationMapView = carPlayMapViewController. navigationMapView
815- navigationMapView. removeRoutes ( )
816- navigationMapView. removeContinuousAlternativesRoutes ( )
817- navigationMapView. removeWaypoints ( )
851+ self . removeRoutesFromMap ( )
818852 if let passiveLocationProvider = navigationMapView. mapView. location. locationProvider as? PassiveLocationProvider {
819853 passiveLocationProvider. locationManager. resumeTripSession ( )
820854 carPlayMapViewController. subscribeForFreeDriveNotifications ( )
@@ -889,10 +923,7 @@ extension CarPlayManager: CPMapTemplateDelegate {
889923 }
890924
891925 public func mapTemplateDidDismissPanningInterface( _ mapTemplate: CPMapTemplate ) {
892- guard let userInfo = mapTemplate. userInfo as? CarPlayUserInfo ,
893- let currentActivity = userInfo [ CarPlayManager . currentActivityKey] as? CarPlayActivity else {
894- return
895- }
926+ guard let currentActivity = mapTemplate. currentActivity else { return }
896927
897928 self . currentActivity = currentActivity
898929
@@ -993,10 +1024,7 @@ extension CarPlayManager: CPMapTemplateDelegate {
9931024 - parameter mapTemplate: `CPMapTemplate` instance, for which buttons update will be performed.
9941025 */
9951026 private func updateNavigationButtons( for mapTemplate: CPMapTemplate ) {
996- guard let userInfo = mapTemplate. userInfo as? CarPlayUserInfo ,
997- let currentActivity = userInfo [ CarPlayManager . currentActivityKey] as? CarPlayActivity else {
998- return
999- }
1027+ guard let currentActivity = mapTemplate. currentActivity else { return }
10001028
10011029 let traitCollection : UITraitCollection
10021030 if let carPlayNavigationViewController = carPlayNavigationViewController {
@@ -1268,6 +1296,7 @@ extension CarPlayManager {
12681296 idleTimerCancellable = nil
12691297
12701298 unsubscribeFromNotifications ( )
1299+ indexedRouteResponse = nil
12711300 }
12721301}
12731302
0 commit comments