@iternio/react-native-auto-play 0.3.9 → 0.3.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/AndroidAutoSession.kt +1 -0
  2. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridMapTemplate.kt +6 -2
  3. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/template/AndroidAutoTemplate.kt +2 -1
  4. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/template/MapTemplate.kt +6 -0
  5. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/utils/BitmapCache.kt +2 -2
  6. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/utils/Debouncer.kt +2 -1
  7. package/ios/hybrid/HybridMapTemplate.swift +9 -5
  8. package/ios/templates/MapTemplate.swift +57 -0
  9. package/ios/templates/Parser.swift +18 -7
  10. package/lib/components/OnAppearedChildRenderer.d.ts +10 -0
  11. package/lib/components/OnAppearedChildRenderer.js +26 -0
  12. package/lib/specs/MapTemplate.nitro.d.ts +2 -0
  13. package/lib/templates/MapTemplate.d.ts +15 -2
  14. package/lib/templates/MapTemplate.js +25 -3
  15. package/lib/types/Maneuver.d.ts +18 -0
  16. package/lib/types/Maneuver.js +13 -0
  17. package/lib/utils/NitroManeuver.d.ts +2 -0
  18. package/lib/utils/NitroMapButton.js +1 -1
  19. package/nitrogen/generated/android/c++/JHybridMapTemplateSpec.cpp +8 -0
  20. package/nitrogen/generated/android/c++/JHybridMapTemplateSpec.hpp +1 -0
  21. package/nitrogen/generated/android/c++/JManeuverState.hpp +64 -0
  22. package/nitrogen/generated/android/c++/JMapTemplateConfig.hpp +5 -1
  23. package/nitrogen/generated/android/c++/JNitroLoadingManeuver.hpp +15 -4
  24. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridMapTemplateSpec.kt +4 -0
  25. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/ManeuverState.kt +25 -0
  26. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/MapTemplateConfig.kt +7 -4
  27. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroLoadingManeuver.kt +9 -3
  28. package/nitrogen/generated/ios/ReactNativeAutoPlay-Swift-Cxx-Umbrella.hpp +3 -0
  29. package/nitrogen/generated/ios/c++/HybridMapTemplateSpecSwift.hpp +9 -0
  30. package/nitrogen/generated/ios/swift/HybridMapTemplateSpec.swift +1 -0
  31. package/nitrogen/generated/ios/swift/HybridMapTemplateSpec_cxx.swift +11 -0
  32. package/nitrogen/generated/ios/swift/ManeuverState.swift +48 -0
  33. package/nitrogen/generated/ios/swift/MapTemplateConfig.swift +12 -1
  34. package/nitrogen/generated/ios/swift/NitroLoadingManeuver.swift +25 -2
  35. package/nitrogen/generated/shared/c++/HybridMapTemplateSpec.cpp +1 -0
  36. package/nitrogen/generated/shared/c++/HybridMapTemplateSpec.hpp +4 -0
  37. package/nitrogen/generated/shared/c++/ManeuverState.hpp +64 -0
  38. package/nitrogen/generated/shared/c++/MapTemplateConfig.hpp +8 -1
  39. package/nitrogen/generated/shared/c++/NitroLoadingManeuver.hpp +15 -4
  40. package/package.json +1 -1
  41. package/src/components/OnAppearedChildRenderer.tsx +37 -0
  42. package/src/specs/MapTemplate.nitro.ts +2 -0
  43. package/src/templates/MapTemplate.ts +40 -4
  44. package/src/types/Maneuver.ts +19 -0
  45. package/src/utils/NitroManeuver.ts +2 -0
  46. package/src/utils/NitroMapButton.ts +1 -1
@@ -55,6 +55,7 @@ class AndroidAutoSession(sessionInfo: SessionInfo) :
55
55
  null,
56
56
  arrayOf(action),
57
57
  null,
58
+ null,
58
59
  null
59
60
  )
60
61
 
@@ -13,7 +13,7 @@ class HybridMapTemplate : HybridMapTemplateSpec() {
13
13
 
14
14
  override fun createMapTemplate(config: MapTemplateConfig) {
15
15
  val context = AndroidAutoSession.getCarContext(config.id) ?: throw IllegalArgumentException(
16
- "createMapTemplate failed, carContext found"
16
+ "createMapTemplate failed, carContext not found"
17
17
  )
18
18
 
19
19
  val template = MapTemplate(context, config, initNavigationManager = true)
@@ -50,7 +50,7 @@ class HybridMapTemplate : HybridMapTemplateSpec() {
50
50
  ) {
51
51
  val carContext = AndroidAutoSession.getCarContext(AndroidAutoSession.ROOT_SESSION)
52
52
  ?: throw IllegalArgumentException(
53
- "dismissNavigationAlert failed, carContext found"
53
+ "dismissNavigationAlert failed, carContext not found"
54
54
  )
55
55
  carContext.getCarService(AppManager::class.java).dismissAlert(navigationAlertId.toInt())
56
56
  }
@@ -154,4 +154,8 @@ class HybridMapTemplate : HybridMapTemplateSpec() {
154
154
  override fun stopNavigation(templateId: String) {
155
155
  MapTemplate.stopNavigation()
156
156
  }
157
+
158
+ override fun setManeuverState(templateId: String, state: ManeuverState) {
159
+ // Android Auto does not have an equivalent to CPManeuverState
160
+ }
157
161
  }
@@ -5,6 +5,7 @@ import androidx.car.app.Screen
5
5
  import androidx.car.app.model.Template
6
6
  import com.margelo.nitro.swe.iternio.reactnativeautoplay.AndroidAutoScreen
7
7
  import com.margelo.nitro.swe.iternio.reactnativeautoplay.NitroAction
8
+ import java.util.concurrent.ConcurrentHashMap
8
9
 
9
10
  abstract class AndroidAutoTemplate<T>(val context: CarContext, var config: T) {
10
11
  abstract fun parse(): Template
@@ -27,7 +28,7 @@ abstract class AndroidAutoTemplate<T>(val context: CarContext, var config: T) {
27
28
 
28
29
  companion object {
29
30
  const val TAG = "AndroidAutoTemplate"
30
- val templates = mutableMapOf<String, AndroidAutoTemplate<*>>()
31
+ val templates = ConcurrentHashMap<String, AndroidAutoTemplate<*>>()
31
32
 
32
33
  fun <T> setTemplate(id: String, template: AndroidAutoTemplate<T>) {
33
34
  templates.put(id, template)
@@ -66,6 +66,10 @@ class MapTemplate(
66
66
  navigationManager.setNavigationManagerCallback(navigationManagerCallback)
67
67
  }
68
68
  }
69
+
70
+ config.defaultGuidanceBackgroundColor?.let { nitroColor ->
71
+ MapTemplate.cardBackgroundColor = Parser.parseColor(nitroColor)
72
+ }
69
73
  }
70
74
 
71
75
  override fun parse(): Template {
@@ -329,7 +333,9 @@ class MapTemplate(
329
333
  }
330
334
 
331
335
  if (loadingInfo != null) {
336
+ cardBackgroundColor = Parser.parseColor(loadingInfo.cardBackgroundColor)
332
337
  navigationInfo = RoutingInfo.Builder().setLoading(true).build()
338
+ AndroidAutoScreen.invalidateSurfaceScreens()
333
339
  return
334
340
  }
335
341
 
@@ -8,8 +8,8 @@ import com.margelo.nitro.swe.iternio.reactnativeautoplay.GlyphImage
8
8
  import com.margelo.nitro.swe.iternio.reactnativeautoplay.NitroColor
9
9
 
10
10
  object BitmapCache {
11
- private val maxMemory = Runtime.getRuntime().maxMemory().toInt()
12
- private val cacheSize = minOf(maxMemory / 8, 8388608) //limit cache to 8 megabyte
11
+ private val maxMemory = Runtime.getRuntime().maxMemory()
12
+ private val cacheSize = minOf(maxMemory / 8, 8388608).toInt() //limit cache to 8 megabyte
13
13
 
14
14
  private val bitmapCache = object : LruCache<String, Bitmap>(cacheSize) {
15
15
  override fun sizeOf(key: String, bitmap: Bitmap): Int {
@@ -7,11 +7,12 @@ import kotlinx.coroutines.delay
7
7
  import kotlinx.coroutines.launch
8
8
 
9
9
  class Debouncer(private val delayMillis: Long = 300L) {
10
+ private val scope = CoroutineScope(Dispatchers.Main)
10
11
  private var debounceJob: Job? = null
11
12
 
12
13
  fun submit(action: () -> Unit) {
13
14
  debounceJob?.cancel()
14
- debounceJob = CoroutineScope(Dispatchers.Main).launch {
15
+ debounceJob = scope.launch {
15
16
  delay(delayMillis)
16
17
  action()
17
18
  }
@@ -138,12 +138,9 @@ class HybridMapTemplate: HybridMapTemplateSpec {
138
138
  {
139
139
  template.updateManeuvers(messageManeuver: messageManeuver)
140
140
  }()
141
- case .third(let loadingManeuver):
141
+ case .third(let loading):
142
142
  {
143
- template.navigationSession?.pauseTrip(
144
- for: .loading,
145
- description: nil
146
- )
143
+ template.updateManeuversLoading(loading: loading)
147
144
  }()
148
145
  }
149
146
 
@@ -164,4 +161,11 @@ class HybridMapTemplate: HybridMapTemplateSpec {
164
161
  template.stopNavigation()
165
162
  }
166
163
  }
164
+
165
+ func setManeuverState(templateId: String, state: ManeuverState) throws {
166
+ try RootModule.withAutoPlayTemplate(templateId: templateId) {
167
+ (template: MapTemplate) in
168
+ template.setManeuverState(state: state)
169
+ }
170
+ }
167
171
  }
@@ -50,6 +50,18 @@ class MapTemplate: AutoPlayHeaderProviding,
50
50
  visibleTravelEstimate = config.visibleTravelEstimate
51
51
 
52
52
  template = CPMapTemplate(id: config.id)
53
+ if let nitroColor = config.defaultGuidanceBackgroundColor,
54
+ let traitCollection = SceneStore.getRootTraitCollection()
55
+ {
56
+ let cardBackgroundColor = Parser.routingManeuverCardBackgroundUIColor(
57
+ color: nitroColor,
58
+ traitCollection: traitCollection
59
+ )
60
+ template.guidanceBackgroundColor = cardBackgroundColor
61
+ }
62
+ else {
63
+ template.guidanceBackgroundColor = .black
64
+ }
53
65
 
54
66
  if let initialProperties = SceneStore.getRootScene()?.initialProperties,
55
67
  let windowDict = initialProperties["window"] as? [String: Any],
@@ -607,6 +619,35 @@ class MapTemplate: AutoPlayHeaderProviding,
607
619
  updateVisibleTravelEstimate(visibleTravelEstimate: nil)
608
620
  }
609
621
 
622
+ func updateManeuversLoading(loading: NitroLoadingManeuver) {
623
+ guard let navigationSession = navigationSession else { return }
624
+
625
+ let description = loading.text
626
+
627
+ guard let traitCollection = SceneStore.getRootTraitCollection() else {
628
+ navigationSession.pauseTrip(for: .loading, description: description)
629
+ return
630
+ }
631
+
632
+ let cardBackgroundColor = Parser.routingManeuverCardBackgroundUIColor(
633
+ color: loading.cardBackgroundColor,
634
+ traitCollection: traitCollection
635
+ )
636
+
637
+ template.guidanceBackgroundColor = cardBackgroundColor
638
+
639
+ if #available(iOS 18.0, *) {
640
+ navigationSession.pauseTrip(
641
+ for: .loading,
642
+ description: description,
643
+ turnCardColor: cardBackgroundColor
644
+ )
645
+ }
646
+ else {
647
+ navigationSession.pauseTrip(for: .loading, description: description)
648
+ }
649
+ }
650
+
610
651
  func updateManeuvers(messageManeuver: NitroMessageManeuver) {
611
652
  guard let navigationSession = navigationSession else { return }
612
653
 
@@ -784,4 +825,20 @@ class MapTemplate: AutoPlayHeaderProviding,
784
825
  navigationSession?.finishTrip()
785
826
  navigationSession = nil
786
827
  }
828
+
829
+ func setManeuverState(state: ManeuverState) {
830
+ guard #available(iOS 17.4, *) else { return }
831
+ guard let navigationSession = navigationSession else { return }
832
+
833
+ switch state {
834
+ case .continue:
835
+ navigationSession.maneuverState = .continue
836
+ case .initial:
837
+ navigationSession.maneuverState = .initial
838
+ case .prepare:
839
+ navigationSession.maneuverState = .prepare
840
+ case .execute:
841
+ navigationSession.maneuverState = .execute
842
+ }
843
+ }
787
844
  }
@@ -503,6 +503,21 @@ class Parser {
503
503
  )
504
504
  }
505
505
 
506
+ /// Card background `UIColor` for routing maneuvers and loading pause — same light/dark component pick as `parseManeuver`.
507
+ static func routingManeuverCardBackgroundUIColor(
508
+ color: NitroColor,
509
+ traitCollection: UITraitCollection
510
+ ) -> UIColor {
511
+ if #available(iOS 15.4, *) {
512
+ let component =
513
+ traitCollection.userInterfaceStyle == .dark
514
+ ? color.darkColor
515
+ : color.lightColor
516
+ return doubleToColor(value: component)
517
+ }
518
+ return parseColor(color: color)
519
+ }
520
+
506
521
  static func parseManeuver(
507
522
  nitroManeuver: NitroRoutingManeuver,
508
523
  traitCollection: UITraitCollection
@@ -528,13 +543,9 @@ class Parser {
528
543
  )
529
544
 
530
545
  if #available(iOS 15.4, *) {
531
- let cardBackgroundColor =
532
- traitCollection.userInterfaceStyle == .dark
533
- ? nitroManeuver.cardBackgroundColor.darkColor
534
- : nitroManeuver.cardBackgroundColor.lightColor
535
-
536
- maneuver.cardBackgroundColor = doubleToColor(
537
- value: cardBackgroundColor
546
+ maneuver.cardBackgroundColor = routingManeuverCardBackgroundUIColor(
547
+ color: nitroManeuver.cardBackgroundColor,
548
+ traitCollection: traitCollection
538
549
  )
539
550
  }
540
551
 
@@ -0,0 +1,10 @@
1
+ type Props = {
2
+ children: React.ReactNode;
3
+ moduleName: string;
4
+ };
5
+ /**
6
+ * renders the passed children when the specified scene/screen appeared
7
+ * this makes sure child hooks are executed only when the map template is ready
8
+ */
9
+ export default function OnAppearedChildRenderer({ children, moduleName }: Props): import("react").ReactNode;
10
+ export {};
@@ -0,0 +1,26 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
3
+ /**
4
+ * renders the passed children when the specified scene/screen appeared
5
+ * this makes sure child hooks are executed only when the map template is ready
6
+ */
7
+ export default function OnAppearedChildRenderer({ children, moduleName }) {
8
+ const [didAppear, setDidAppear] = useState(false);
9
+ useEffect(() => {
10
+ let remove = HybridAutoPlay.addListenerRenderState(moduleName, (renderState) => {
11
+ if (renderState === 'didAppear') {
12
+ remove?.();
13
+ remove = null;
14
+ setDidAppear(true);
15
+ }
16
+ });
17
+ return () => {
18
+ remove?.();
19
+ remove = null;
20
+ };
21
+ }, [moduleName]);
22
+ if (didAppear) {
23
+ return children;
24
+ }
25
+ return null;
26
+ }
@@ -1,5 +1,6 @@
1
1
  import type { HybridObject } from 'react-native-nitro-modules';
2
2
  import type { NitroMapTemplateConfig, TripSelectorCallback, VisibleTravelEstimate } from '../templates/MapTemplate';
3
+ import type { ManeuverState } from '../types/Maneuver';
3
4
  import type { AutoText } from '../types/Text';
4
5
  import type { TripConfig, TripPoint, TripPreviewTextConfiguration, TripsConfig } from '../types/Trip';
5
6
  import type { NitroNavigationAlert } from '../utils/NitroAlert';
@@ -24,5 +25,6 @@ export interface MapTemplate extends HybridObject<{
24
25
  updateManeuvers(templateId: string, maneuvers: NitroManeuver): void;
25
26
  startNavigation(templateId: string, trip: TripConfig): void;
26
27
  stopNavigation(templateId: string): void;
28
+ setManeuverState(templateId: string, state: ManeuverState): void;
27
29
  }
28
30
  export {};
@@ -1,11 +1,12 @@
1
1
  import React from 'react';
2
2
  import type { AutoText } from '..';
3
3
  import type { ActionButtonAndroid, MapButton, MapPanButton } from '../types/Button';
4
- import type { AutoManeuver } from '../types/Maneuver';
4
+ import type { AutoManeuver, ManeuverState } from '../types/Maneuver';
5
5
  import type { ColorScheme, RootComponentInitialProps } from '../types/RootComponent';
6
6
  import type { TripConfig, TripPoint, TripPreviewTextConfiguration, TripsConfig } from '../types/Trip';
7
7
  import { type NitroAction } from '../utils/NitroAction';
8
8
  import { type NavigationAlert } from '../utils/NitroAlert';
9
+ import { type NitroColor, type ThemedColor } from '../utils/NitroColor';
9
10
  import { NitroMapButton } from '../utils/NitroMapButton';
10
11
  import { type HeaderActionsIos, type NitroBaseMapTemplateConfig, Template, type TemplateConfig } from './Template';
11
12
  export type Point = {
@@ -53,6 +54,7 @@ export interface NitroMapTemplateConfig extends TemplateConfig, NitroBaseMapTemp
53
54
  onAutoDriveEnabled?: () => void;
54
55
  mapButtons?: Array<NitroMapButton>;
55
56
  headerActions?: Array<NitroAction>;
57
+ defaultGuidanceBackgroundColor?: NitroColor;
56
58
  /**
57
59
  * specify the percentage of screen height/width the pan button should scroll
58
60
  * @namespace iOS
@@ -78,7 +80,7 @@ export type BaseMapTemplateConfig<T> = {
78
80
  */
79
81
  headerActions?: MapHeaderActions<T>;
80
82
  };
81
- export type MapTemplateConfig = Omit<NitroMapTemplateConfig, 'mapButtons' | 'headerActions' | 'onStopNavigation' | 'onAutoDriveEnabled'> & BaseMapTemplateConfig<MapTemplate> & {
83
+ export type MapTemplateConfig = Omit<NitroMapTemplateConfig, 'mapButtons' | 'headerActions' | 'onStopNavigation' | 'onAutoDriveEnabled' | 'defaultGuidanceBackgroundColor'> & BaseMapTemplateConfig<MapTemplate> & {
82
84
  /**
83
85
  * react component that is rendered
84
86
  */
@@ -93,6 +95,10 @@ export type MapTemplateConfig = Omit<NitroMapTemplateConfig, 'mapButtons' | 'hea
93
95
  * @namespace Android
94
96
  */
95
97
  onAutoDriveEnabled?: (template: MapTemplate) => void;
98
+ /**
99
+ * Initial navigation maneuver background color. Mainly useful, when in CarPlay the default loading maneuver does not have the right color.
100
+ */
101
+ defaultGuidanceBackgroundColor?: ThemedColor | string;
96
102
  };
97
103
  export interface TripSelectorCallback {
98
104
  setSelectedTrip: (id: string) => void;
@@ -148,4 +154,11 @@ export declare class MapTemplate extends Template<MapTemplateConfig, MapTemplate
148
154
  */
149
155
  startNavigation(trip: TripConfig): void;
150
156
  stopNavigation(): void;
157
+ /**
158
+ * Sets the current maneuver state indicating progress within a maneuver.
159
+ * Transition through: continue → initial → prepare → execute → continue
160
+ * @namespace iOS sets CPManeuverState on the CPNavigationSession, used by instrument cluster and HUD
161
+ * @namespace Android no-op, Android Auto does not have an equivalent API
162
+ */
163
+ setManeuverState(state: ManeuverState): void;
151
164
  }
@@ -2,10 +2,12 @@ import React from 'react';
2
2
  import { AppRegistry, Platform } from 'react-native';
3
3
  import { NitroModules } from 'react-native-nitro-modules';
4
4
  import { MapTemplateProvider } from '../components/MapTemplateContext';
5
+ import OnAppearedChildRenderer from '../components/OnAppearedChildRenderer';
5
6
  import { SafeAreaInsetsProvider } from '../components/SafeAreaInsetsContext';
6
7
  import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
7
8
  import { NitroActionUtil } from '../utils/NitroAction';
8
9
  import { NitroAlertUtil } from '../utils/NitroAlert';
10
+ import { NitroColorUtil } from '../utils/NitroColor';
9
11
  import { NitroManeuverUtil } from '../utils/NitroManeuver';
10
12
  import { NitroMapButton } from '../utils/NitroMapButton';
11
13
  import { Template, } from './Template';
@@ -15,14 +17,18 @@ export class MapTemplate extends Template {
15
17
  template = this;
16
18
  constructor(config) {
17
19
  super(config);
18
- const { component, mapButtons, headerActions, onStopNavigation, onAutoDriveEnabled, ...baseConfig } = config;
20
+ const { component, mapButtons, headerActions, onStopNavigation, onAutoDriveEnabled, defaultGuidanceBackgroundColor, ...baseConfig } = config;
19
21
  AppRegistry.registerComponent(this.id, () => (props) => React.createElement(MapTemplateProvider, {
20
22
  mapTemplate: this.template,
21
23
  // biome-ignore lint/correctness/noChildrenProp: there is no other way in a ts file
22
24
  children: React.createElement(SafeAreaInsetsProvider, {
23
25
  moduleName: this.id,
24
26
  // biome-ignore lint/correctness/noChildrenProp: there is no other way in a ts file
25
- children: React.createElement(component, props),
27
+ children: React.createElement(OnAppearedChildRenderer, {
28
+ // biome-ignore lint/correctness/noChildrenProp: there is no other way in a ts file
29
+ children: React.createElement(component, props),
30
+ moduleName: this.id,
31
+ }),
26
32
  }),
27
33
  }));
28
34
  const nitroConfig = {
@@ -32,6 +38,9 @@ export class MapTemplate extends Template {
32
38
  mapButtons: NitroMapButton.convert(this.template, mapButtons),
33
39
  onStopNavigation: () => onStopNavigation(this.template),
34
40
  onAutoDriveEnabled: onAutoDriveEnabled ? () => onAutoDriveEnabled(this.template) : undefined,
41
+ defaultGuidanceBackgroundColor: defaultGuidanceBackgroundColor != null
42
+ ? NitroColorUtil.convert(defaultGuidanceBackgroundColor)
43
+ : undefined,
35
44
  };
36
45
  HybridMapTemplate.createMapTemplate(nitroConfig);
37
46
  }
@@ -106,7 +115,11 @@ export class MapTemplate extends Template {
106
115
  return;
107
116
  }
108
117
  if (maneuvers.type === 'loading') {
109
- HybridMapTemplate.updateManeuvers(this.id, { isLoading: true });
118
+ HybridMapTemplate.updateManeuvers(this.id, {
119
+ isLoading: true,
120
+ cardBackgroundColor: NitroColorUtil.convert(maneuvers.cardBackgroundColor),
121
+ text: maneuvers.text != null ? maneuvers.text : undefined,
122
+ });
110
123
  return;
111
124
  }
112
125
  const messageManeuver = NitroManeuverUtil.convert(maneuvers);
@@ -122,4 +135,13 @@ export class MapTemplate extends Template {
122
135
  stopNavigation() {
123
136
  HybridMapTemplate.stopNavigation(this.id);
124
137
  }
138
+ /**
139
+ * Sets the current maneuver state indicating progress within a maneuver.
140
+ * Transition through: continue → initial → prepare → execute → continue
141
+ * @namespace iOS sets CPManeuverState on the CPNavigationSession, used by instrument cluster and HUD
142
+ * @namespace Android no-op, Android Auto does not have an equivalent API
143
+ */
144
+ setManeuverState(state) {
145
+ HybridMapTemplate.setManeuverState(this.id, state);
146
+ }
125
147
  }
@@ -56,6 +56,18 @@ export declare enum KeepType {
56
56
  Right = 1,// Android TYPE_KEEP_RIGHT, iOS keepRight
57
57
  FollowRoad = 2
58
58
  }
59
+ /**
60
+ * Describes the progress within a maneuver.
61
+ * Transition through: Continue → Initial → Prepare → Execute → Continue
62
+ * @namespace iOS sets CPManeuverState on the CPNavigationSession
63
+ * @namespace Android no-op, Android Auto does not have an equivalent API
64
+ */
65
+ export declare enum ManeuverState {
66
+ Continue = 0,// iOS .continue
67
+ Initial = 1,// iOS .initial
68
+ Prepare = 2,// iOS .prepare
69
+ Execute = 3
70
+ }
59
71
  export interface BaseManeuver {
60
72
  /**
61
73
  * @namespace iOS specify a unique identifier, sending over a Maneuver with a known id will only update the travelEstimates on the previously sent Maneuver
@@ -198,6 +210,12 @@ export type MessageManeuver = {
198
210
  };
199
211
  export type LoadingManeuver = {
200
212
  type: 'loading';
213
+ cardBackgroundColor: ThemedColor | string;
214
+ /**
215
+ * @namespace iOS CarPlay — shows text on the loading maneuver card
216
+ * @namespace Android Auto — not supported
217
+ */
218
+ text?: string;
201
219
  };
202
220
  export type AutoManeuver = (Array<RoutingManeuver> & {
203
221
  length: 0 | 1 | 2;
@@ -59,3 +59,16 @@ export var KeepType;
59
59
  KeepType[KeepType["Right"] = 1] = "Right";
60
60
  KeepType[KeepType["FollowRoad"] = 2] = "FollowRoad";
61
61
  })(KeepType || (KeepType = {}));
62
+ /**
63
+ * Describes the progress within a maneuver.
64
+ * Transition through: Continue → Initial → Prepare → Execute → Continue
65
+ * @namespace iOS sets CPManeuverState on the CPNavigationSession
66
+ * @namespace Android no-op, Android Auto does not have an equivalent API
67
+ */
68
+ export var ManeuverState;
69
+ (function (ManeuverState) {
70
+ ManeuverState[ManeuverState["Continue"] = 0] = "Continue";
71
+ ManeuverState[ManeuverState["Initial"] = 1] = "Initial";
72
+ ManeuverState[ManeuverState["Prepare"] = 2] = "Prepare";
73
+ ManeuverState[ManeuverState["Execute"] = 3] = "Execute";
74
+ })(ManeuverState || (ManeuverState = {}));
@@ -35,6 +35,8 @@ export interface NitroMessageManeuver {
35
35
  }
36
36
  interface NitroLoadingManeuver {
37
37
  isLoading: true;
38
+ cardBackgroundColor: NitroColor;
39
+ text?: string;
38
40
  }
39
41
  export type NitroManeuver = Array<NitroRoutingManeuver> | NitroMessageManeuver | NitroLoadingManeuver;
40
42
  declare function convert(autoManeuver: MessageManeuver): NitroMessageManeuver;
@@ -13,7 +13,7 @@ const convert = (template, mapButtons) => {
13
13
  : 'backgroundColor' in button.image
14
14
  ? button.image.backgroundColor
15
15
  : 'transparent';
16
- const fontScale = (button.image.fontScale ?? Platform.OS === 'android') ? 1.0 : 0.65;
16
+ const fontScale = button.image.fontScale ?? (Platform.OS === 'android' ? 1.0 : 0.65);
17
17
  return {
18
18
  type,
19
19
  onPress,
@@ -93,6 +93,8 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay { enum class Traffic
93
93
  namespace margelo::nitro::swe::iternio::reactnativeautoplay { enum class ManeuverType; }
94
94
  // Forward declaration of `TripConfig` to properly resolve imports.
95
95
  namespace margelo::nitro::swe::iternio::reactnativeautoplay { struct TripConfig; }
96
+ // Forward declaration of `ManeuverState` to properly resolve imports.
97
+ namespace margelo::nitro::swe::iternio::reactnativeautoplay { enum class ManeuverState; }
96
98
 
97
99
  #include "TripSelectorCallback.hpp"
98
100
  #include "JTripSelectorCallback.hpp"
@@ -203,6 +205,8 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay { struct TripConfig;
203
205
  #include "JNitroLoadingManeuver.hpp"
204
206
  #include "TripConfig.hpp"
205
207
  #include "JTripConfig.hpp"
208
+ #include "ManeuverState.hpp"
209
+ #include "JManeuverState.hpp"
206
210
 
207
211
  namespace margelo::nitro::swe::iternio::reactnativeautoplay {
208
212
 
@@ -333,5 +337,9 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
333
337
  static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JString> /* templateId */)>("stopNavigation");
334
338
  method(_javaPart, jni::make_jstring(templateId));
335
339
  }
340
+ void JHybridMapTemplateSpec::setManeuverState(const std::string& templateId, ManeuverState state) {
341
+ static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JString> /* templateId */, jni::alias_ref<JManeuverState> /* state */)>("setManeuverState");
342
+ method(_javaPart, jni::make_jstring(templateId), JManeuverState::fromCpp(state));
343
+ }
336
344
 
337
345
  } // namespace margelo::nitro::swe::iternio::reactnativeautoplay
@@ -66,6 +66,7 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
66
66
  void updateManeuvers(const std::string& templateId, const std::variant<std::vector<NitroRoutingManeuver>, NitroMessageManeuver, NitroLoadingManeuver>& maneuvers) override;
67
67
  void startNavigation(const std::string& templateId, const TripConfig& trip) override;
68
68
  void stopNavigation(const std::string& templateId) override;
69
+ void setManeuverState(const std::string& templateId, ManeuverState state) override;
69
70
 
70
71
  private:
71
72
  jni::global_ref<JHybridMapTemplateSpec::JavaPart> _javaPart;
@@ -0,0 +1,64 @@
1
+ ///
2
+ /// JManeuverState.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #include <fbjni/fbjni.h>
11
+ #include "ManeuverState.hpp"
12
+
13
+ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
14
+
15
+ using namespace facebook;
16
+
17
+ /**
18
+ * The C++ JNI bridge between the C++ enum "ManeuverState" and the the Kotlin enum "ManeuverState".
19
+ */
20
+ struct JManeuverState final: public jni::JavaClass<JManeuverState> {
21
+ public:
22
+ static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/swe/iternio/reactnativeautoplay/ManeuverState;";
23
+
24
+ public:
25
+ /**
26
+ * Convert this Java/Kotlin-based enum to the C++ enum ManeuverState.
27
+ */
28
+ [[maybe_unused]]
29
+ [[nodiscard]]
30
+ ManeuverState toCpp() const {
31
+ static const auto clazz = javaClassStatic();
32
+ static const auto fieldOrdinal = clazz->getField<int>("value");
33
+ int ordinal = this->getFieldValue(fieldOrdinal);
34
+ return static_cast<ManeuverState>(ordinal);
35
+ }
36
+
37
+ public:
38
+ /**
39
+ * Create a Java/Kotlin-based enum with the given C++ enum's value.
40
+ */
41
+ [[maybe_unused]]
42
+ static jni::alias_ref<JManeuverState> fromCpp(ManeuverState value) {
43
+ static const auto clazz = javaClassStatic();
44
+ switch (value) {
45
+ case ManeuverState::CONTINUE:
46
+ static const auto fieldCONTINUE = clazz->getStaticField<JManeuverState>("CONTINUE");
47
+ return clazz->getStaticFieldValue(fieldCONTINUE);
48
+ case ManeuverState::INITIAL:
49
+ static const auto fieldINITIAL = clazz->getStaticField<JManeuverState>("INITIAL");
50
+ return clazz->getStaticFieldValue(fieldINITIAL);
51
+ case ManeuverState::PREPARE:
52
+ static const auto fieldPREPARE = clazz->getStaticField<JManeuverState>("PREPARE");
53
+ return clazz->getStaticFieldValue(fieldPREPARE);
54
+ case ManeuverState::EXECUTE:
55
+ static const auto fieldEXECUTE = clazz->getStaticField<JManeuverState>("EXECUTE");
56
+ return clazz->getStaticFieldValue(fieldEXECUTE);
57
+ default:
58
+ std::string stringValue = std::to_string(static_cast<int>(value));
59
+ throw std::invalid_argument("Invalid enum value (" + stringValue + "!");
60
+ }
61
+ }
62
+ };
63
+
64
+ } // namespace margelo::nitro::swe::iternio::reactnativeautoplay
@@ -103,6 +103,8 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
103
103
  jni::local_ref<jni::JArrayClass<JNitroMapButton>> mapButtons = this->getFieldValue(fieldMapButtons);
104
104
  static const auto fieldHeaderActions = clazz->getField<jni::JArrayClass<JNitroAction>>("headerActions");
105
105
  jni::local_ref<jni::JArrayClass<JNitroAction>> headerActions = this->getFieldValue(fieldHeaderActions);
106
+ static const auto fieldDefaultGuidanceBackgroundColor = clazz->getField<JNitroColor>("defaultGuidanceBackgroundColor");
107
+ jni::local_ref<JNitroColor> defaultGuidanceBackgroundColor = this->getFieldValue(fieldDefaultGuidanceBackgroundColor);
106
108
  static const auto fieldPanButtonScrollPercentage = clazz->getField<jni::JDouble>("panButtonScrollPercentage");
107
109
  jni::local_ref<jni::JDouble> panButtonScrollPercentage = this->getFieldValue(fieldPanButtonScrollPercentage);
108
110
  static const auto fieldOnDidChangePanningInterface = clazz->getField<JFunc_void_bool::javaobject>("onDidChangePanningInterface");
@@ -239,6 +241,7 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
239
241
  }
240
242
  return __vector;
241
243
  }()) : std::nullopt,
244
+ defaultGuidanceBackgroundColor != nullptr ? std::make_optional(defaultGuidanceBackgroundColor->toCpp()) : std::nullopt,
242
245
  panButtonScrollPercentage != nullptr ? std::make_optional(panButtonScrollPercentage->value()) : std::nullopt,
243
246
  onDidChangePanningInterface != nullptr ? std::make_optional([&]() -> std::function<void(bool /* isPanningInterfaceVisible */)> {
244
247
  if (onDidChangePanningInterface->isInstanceOf(JFunc_void_bool_cxx::javaClassStatic())) [[likely]] {
@@ -258,7 +261,7 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
258
261
  */
259
262
  [[maybe_unused]]
260
263
  static jni::local_ref<JMapTemplateConfig::javaobject> fromCpp(const MapTemplateConfig& value) {
261
- using JSignature = JMapTemplateConfig(jni::alias_ref<jni::JString>, jni::alias_ref<JFunc_void_std__optional_bool_::javaobject>, jni::alias_ref<JFunc_void_std__optional_bool_::javaobject>, jni::alias_ref<JFunc_void_std__optional_bool_::javaobject>, jni::alias_ref<JFunc_void_std__optional_bool_::javaobject>, jni::alias_ref<JFunc_void::javaobject>, jni::alias_ref<jni::JDouble>, jni::alias_ref<JVisibleTravelEstimate>, jni::alias_ref<JFunc_void_Point_std__optional_Point_::javaobject>, jni::alias_ref<JFunc_void_Point_double::javaobject>, jni::alias_ref<JFunc_void_Point::javaobject>, jni::alias_ref<JFunc_void_Point::javaobject>, jni::alias_ref<JFunc_void_ColorScheme::javaobject>, jni::alias_ref<JFunc_void::javaobject>, jni::alias_ref<JFunc_void::javaobject>, jni::alias_ref<jni::JArrayClass<JNitroMapButton>>, jni::alias_ref<jni::JArrayClass<JNitroAction>>, jni::alias_ref<jni::JDouble>, jni::alias_ref<JFunc_void_bool::javaobject>);
264
+ using JSignature = JMapTemplateConfig(jni::alias_ref<jni::JString>, jni::alias_ref<JFunc_void_std__optional_bool_::javaobject>, jni::alias_ref<JFunc_void_std__optional_bool_::javaobject>, jni::alias_ref<JFunc_void_std__optional_bool_::javaobject>, jni::alias_ref<JFunc_void_std__optional_bool_::javaobject>, jni::alias_ref<JFunc_void::javaobject>, jni::alias_ref<jni::JDouble>, jni::alias_ref<JVisibleTravelEstimate>, jni::alias_ref<JFunc_void_Point_std__optional_Point_::javaobject>, jni::alias_ref<JFunc_void_Point_double::javaobject>, jni::alias_ref<JFunc_void_Point::javaobject>, jni::alias_ref<JFunc_void_Point::javaobject>, jni::alias_ref<JFunc_void_ColorScheme::javaobject>, jni::alias_ref<JFunc_void::javaobject>, jni::alias_ref<JFunc_void::javaobject>, jni::alias_ref<jni::JArrayClass<JNitroMapButton>>, jni::alias_ref<jni::JArrayClass<JNitroAction>>, jni::alias_ref<JNitroColor>, jni::alias_ref<jni::JDouble>, jni::alias_ref<JFunc_void_bool::javaobject>);
262
265
  static const auto clazz = javaClassStatic();
263
266
  static const auto create = clazz->getStaticMethod<JSignature>("fromCpp");
264
267
  return create(
@@ -298,6 +301,7 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
298
301
  }
299
302
  return __array;
300
303
  }() : nullptr,
304
+ value.defaultGuidanceBackgroundColor.has_value() ? JNitroColor::fromCpp(value.defaultGuidanceBackgroundColor.value()) : nullptr,
301
305
  value.panButtonScrollPercentage.has_value() ? jni::JDouble::valueOf(value.panButtonScrollPercentage.value()) : nullptr,
302
306
  value.onDidChangePanningInterface.has_value() ? JFunc_void_bool_cxx::fromCpp(value.onDidChangePanningInterface.value()) : nullptr
303
307
  );