@iternio/react-native-auto-play 0.3.8 → 0.3.10

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 (36) hide show
  1. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/AndroidAutoService.kt +0 -2
  2. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/AndroidAutoSession.kt +1 -0
  3. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridMapTemplate.kt +6 -2
  4. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/VirtualRenderer.kt +5 -6
  5. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/template/AndroidAutoTemplate.kt +2 -1
  6. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/utils/BitmapCache.kt +2 -2
  7. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/utils/Debouncer.kt +2 -1
  8. package/ios/hybrid/HybridMapTemplate.swift +7 -0
  9. package/ios/templates/MapTemplate.swift +16 -0
  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 +8 -1
  14. package/lib/templates/MapTemplate.js +15 -1
  15. package/lib/types/Maneuver.d.ts +12 -0
  16. package/lib/types/Maneuver.js +13 -0
  17. package/lib/utils/NitroMapButton.js +1 -1
  18. package/nitrogen/generated/android/c++/JHybridMapTemplateSpec.cpp +8 -0
  19. package/nitrogen/generated/android/c++/JHybridMapTemplateSpec.hpp +1 -0
  20. package/nitrogen/generated/android/c++/JManeuverState.hpp +64 -0
  21. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridMapTemplateSpec.kt +4 -0
  22. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/ManeuverState.kt +25 -0
  23. package/nitrogen/generated/ios/ReactNativeAutoPlay-Swift-Cxx-Umbrella.hpp +3 -0
  24. package/nitrogen/generated/ios/c++/HybridMapTemplateSpecSwift.hpp +9 -0
  25. package/nitrogen/generated/ios/swift/HybridMapTemplateSpec.swift +1 -0
  26. package/nitrogen/generated/ios/swift/HybridMapTemplateSpec_cxx.swift +11 -0
  27. package/nitrogen/generated/ios/swift/ManeuverState.swift +48 -0
  28. package/nitrogen/generated/shared/c++/HybridMapTemplateSpec.cpp +1 -0
  29. package/nitrogen/generated/shared/c++/HybridMapTemplateSpec.hpp +4 -0
  30. package/nitrogen/generated/shared/c++/ManeuverState.hpp +64 -0
  31. package/package.json +1 -1
  32. package/src/components/OnAppearedChildRenderer.tsx +37 -0
  33. package/src/specs/MapTemplate.nitro.ts +2 -0
  34. package/src/templates/MapTemplate.ts +17 -2
  35. package/src/types/Maneuver.ts +13 -0
  36. package/src/utils/NitroMapButton.ts +1 -1
@@ -81,8 +81,6 @@ class AndroidAutoService : CarAppService() {
81
81
  stopForeground(STOP_FOREGROUND_REMOVE)
82
82
 
83
83
  NitroModules.applicationContext?.removeLifecycleEventListener(reactLifecycleObserver)
84
-
85
- VirtualRenderer.remove()
86
84
  }
87
85
 
88
86
  private val reactLifecycleObserver = object : LifecycleEventListener {
@@ -208,6 +208,7 @@ class AndroidAutoSession(sessionInfo: SessionInfo) :
208
208
 
209
209
  override fun onDestroy(owner: LifecycleOwner) {
210
210
  sessions.remove(moduleName)
211
+ VirtualRenderer.removeRenderer(moduleName)
211
212
  clusterId?.let {
212
213
  HybridCluster.emit(ClusterEventName.DIDDISCONNECT, clusterId)
213
214
  clusterSessions.remove(it)
@@ -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
  }
@@ -77,8 +77,6 @@ class VirtualRenderer(
77
77
  return
78
78
  }
79
79
 
80
- virtualDisplay?.release() // in case this is called multiple times release the old instance
81
-
82
80
  val manager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
83
81
  virtualDisplay = manager.createVirtualDisplay(
84
82
  moduleName,
@@ -97,7 +95,8 @@ class VirtualRenderer(
97
95
  }
98
96
 
99
97
  override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) {
100
- stop()
98
+ virtualDisplay?.release()
99
+ virtualDisplay = null
101
100
  }
102
101
 
103
102
  override fun onScroll(distanceX: Float, distanceY: Float) {
@@ -426,9 +425,9 @@ class VirtualRenderer(
426
425
  return virtualRenderer.contains(moduleId)
427
426
  }
428
427
 
429
- fun remove() {
430
- virtualRenderer.forEach { (_, renderer) -> renderer.stop() }
431
- virtualRenderer.clear()
428
+ fun removeRenderer(moduleId: String) {
429
+ virtualRenderer[moduleId]?.stop()
430
+ virtualRenderer.remove(moduleId)
432
431
  }
433
432
  }
434
433
  }
@@ -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)
@@ -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
  }
@@ -164,4 +164,11 @@ class HybridMapTemplate: HybridMapTemplateSpec {
164
164
  template.stopNavigation()
165
165
  }
166
166
  }
167
+
168
+ func setManeuverState(templateId: String, state: ManeuverState) throws {
169
+ try RootModule.withAutoPlayTemplate(templateId: templateId) {
170
+ (template: MapTemplate) in
171
+ template.setManeuverState(state: state)
172
+ }
173
+ }
167
174
  }
@@ -784,4 +784,20 @@ class MapTemplate: AutoPlayHeaderProviding,
784
784
  navigationSession?.finishTrip()
785
785
  navigationSession = nil
786
786
  }
787
+
788
+ func setManeuverState(state: ManeuverState) {
789
+ guard #available(iOS 17.4, *) else { return }
790
+ guard let navigationSession = navigationSession else { return }
791
+
792
+ switch state {
793
+ case .continue:
794
+ navigationSession.maneuverState = .continue
795
+ case .initial:
796
+ navigationSession.maneuverState = .initial
797
+ case .prepare:
798
+ navigationSession.maneuverState = .prepare
799
+ case .execute:
800
+ navigationSession.maneuverState = .execute
801
+ }
802
+ }
787
803
  }
@@ -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,7 +1,7 @@
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';
@@ -148,4 +148,11 @@ export declare class MapTemplate extends Template<MapTemplateConfig, MapTemplate
148
148
  */
149
149
  startNavigation(trip: TripConfig): void;
150
150
  stopNavigation(): void;
151
+ /**
152
+ * Sets the current maneuver state indicating progress within a maneuver.
153
+ * Transition through: continue → initial → prepare → execute → continue
154
+ * @namespace iOS sets CPManeuverState on the CPNavigationSession, used by instrument cluster and HUD
155
+ * @namespace Android no-op, Android Auto does not have an equivalent API
156
+ */
157
+ setManeuverState(state: ManeuverState): void;
151
158
  }
@@ -2,6 +2,7 @@ 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';
@@ -22,7 +23,11 @@ export class MapTemplate extends Template {
22
23
  children: React.createElement(SafeAreaInsetsProvider, {
23
24
  moduleName: this.id,
24
25
  // biome-ignore lint/correctness/noChildrenProp: there is no other way in a ts file
25
- children: React.createElement(component, props),
26
+ children: React.createElement(OnAppearedChildRenderer, {
27
+ // biome-ignore lint/correctness/noChildrenProp: there is no other way in a ts file
28
+ children: React.createElement(component, props),
29
+ moduleName: this.id,
30
+ }),
26
31
  }),
27
32
  }));
28
33
  const nitroConfig = {
@@ -122,4 +127,13 @@ export class MapTemplate extends Template {
122
127
  stopNavigation() {
123
128
  HybridMapTemplate.stopNavigation(this.id);
124
129
  }
130
+ /**
131
+ * Sets the current maneuver state indicating progress within a maneuver.
132
+ * Transition through: continue → initial → prepare → execute → continue
133
+ * @namespace iOS sets CPManeuverState on the CPNavigationSession, used by instrument cluster and HUD
134
+ * @namespace Android no-op, Android Auto does not have an equivalent API
135
+ */
136
+ setManeuverState(state) {
137
+ HybridMapTemplate.setManeuverState(this.id, state);
138
+ }
125
139
  }
@@ -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
@@ -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 = {}));
@@ -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
@@ -81,6 +81,10 @@ abstract class HybridMapTemplateSpec: HybridObject() {
81
81
  @DoNotStrip
82
82
  @Keep
83
83
  abstract fun stopNavigation(templateId: String): Unit
84
+
85
+ @DoNotStrip
86
+ @Keep
87
+ abstract fun setManeuverState(templateId: String, state: ManeuverState): Unit
84
88
 
85
89
  // Default implementation of `HybridObject.toString()`
86
90
  override fun toString(): String {
@@ -0,0 +1,25 @@
1
+ ///
2
+ /// ManeuverState.kt
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
+ package com.margelo.nitro.swe.iternio.reactnativeautoplay
9
+
10
+ import androidx.annotation.Keep
11
+ import com.facebook.proguard.annotations.DoNotStrip
12
+
13
+ /**
14
+ * Represents the JavaScript enum/union "ManeuverState".
15
+ */
16
+ @DoNotStrip
17
+ @Keep
18
+ enum class ManeuverState(@DoNotStrip @Keep val value: Int) {
19
+ CONTINUE(0),
20
+ INITIAL(1),
21
+ PREPARE(2),
22
+ EXECUTE(3);
23
+
24
+ companion object
25
+ }
@@ -64,6 +64,8 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay { struct LaneGuidanc
64
64
  namespace margelo::nitro::swe::iternio::reactnativeautoplay { struct ListTemplateConfig; }
65
65
  // Forward declaration of `Location` to properly resolve imports.
66
66
  namespace margelo::nitro::swe::iternio::reactnativeautoplay { struct Location; }
67
+ // Forward declaration of `ManeuverState` to properly resolve imports.
68
+ namespace margelo::nitro::swe::iternio::reactnativeautoplay { enum class ManeuverState; }
67
69
  // Forward declaration of `ManeuverType` to properly resolve imports.
68
70
  namespace margelo::nitro::swe::iternio::reactnativeautoplay { enum class ManeuverType; }
69
71
  // Forward declaration of `MapTemplateConfig` to properly resolve imports.
@@ -176,6 +178,7 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay { enum class ZoomEve
176
178
  #include "LaneGuidance.hpp"
177
179
  #include "ListTemplateConfig.hpp"
178
180
  #include "Location.hpp"
181
+ #include "ManeuverState.hpp"
179
182
  #include "ManeuverType.hpp"
180
183
  #include "MapTemplateConfig.hpp"
181
184
  #include "MessageTemplateConfig.hpp"
@@ -98,6 +98,8 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay { enum class Traffic
98
98
  namespace margelo::nitro::swe::iternio::reactnativeautoplay { enum class ManeuverType; }
99
99
  // Forward declaration of `TripConfig` to properly resolve imports.
100
100
  namespace margelo::nitro::swe::iternio::reactnativeautoplay { struct TripConfig; }
101
+ // Forward declaration of `ManeuverState` to properly resolve imports.
102
+ namespace margelo::nitro::swe::iternio::reactnativeautoplay { enum class ManeuverState; }
101
103
 
102
104
  #include "MapTemplateConfig.hpp"
103
105
  #include <string>
@@ -148,6 +150,7 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay { struct TripConfig;
148
150
  #include "TrafficSide.hpp"
149
151
  #include "ManeuverType.hpp"
150
152
  #include "TripConfig.hpp"
153
+ #include "ManeuverState.hpp"
151
154
 
152
155
  #include "ReactNativeAutoPlay-Swift-Cxx-Umbrella.hpp"
153
156
 
@@ -275,6 +278,12 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
275
278
  std::rethrow_exception(__result.error());
276
279
  }
277
280
  }
281
+ inline void setManeuverState(const std::string& templateId, ManeuverState state) override {
282
+ auto __result = _swiftPart.setManeuverState(templateId, static_cast<int>(state));
283
+ if (__result.hasError()) [[unlikely]] {
284
+ std::rethrow_exception(__result.error());
285
+ }
286
+ }
278
287
 
279
288
  private:
280
289
  ReactNativeAutoPlay::HybridMapTemplateSpec_cxx _swiftPart;
@@ -25,6 +25,7 @@ public protocol HybridMapTemplateSpec_protocol: HybridObject {
25
25
  func updateManeuvers(templateId: String, maneuvers: NitroManeuver) throws -> Void
26
26
  func startNavigation(templateId: String, trip: TripConfig) throws -> Void
27
27
  func stopNavigation(templateId: String) throws -> Void
28
+ func setManeuverState(templateId: String, state: ManeuverState) throws -> Void
28
29
  }
29
30
 
30
31
  public extension HybridMapTemplateSpec_protocol {
@@ -308,4 +308,15 @@ open class HybridMapTemplateSpec_cxx {
308
308
  return bridge.create_Result_void_(__exceptionPtr)
309
309
  }
310
310
  }
311
+
312
+ @inline(__always)
313
+ public final func setManeuverState(templateId: std.string, state: Int32) -> bridge.Result_void_ {
314
+ do {
315
+ try self.__implementation.setManeuverState(templateId: String(templateId), state: margelo.nitro.swe.iternio.reactnativeautoplay.ManeuverState(rawValue: state)!)
316
+ return bridge.create_Result_void_()
317
+ } catch (let __error) {
318
+ let __exceptionPtr = __error.toCpp()
319
+ return bridge.create_Result_void_(__exceptionPtr)
320
+ }
321
+ }
311
322
  }
@@ -0,0 +1,48 @@
1
+ ///
2
+ /// ManeuverState.swift
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
+ /**
9
+ * Represents the JS enum `ManeuverState`, backed by a C++ enum.
10
+ */
11
+ public typealias ManeuverState = margelo.nitro.swe.iternio.reactnativeautoplay.ManeuverState
12
+
13
+ public extension ManeuverState {
14
+ /**
15
+ * Get a ManeuverState for the given String value, or
16
+ * return `nil` if the given value was invalid/unknown.
17
+ */
18
+ init?(fromString string: String) {
19
+ switch string {
20
+ case "Continue":
21
+ self = .continue
22
+ case "Initial":
23
+ self = .initial
24
+ case "Prepare":
25
+ self = .prepare
26
+ case "Execute":
27
+ self = .execute
28
+ default:
29
+ return nil
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Get the String value this ManeuverState represents.
35
+ */
36
+ var stringValue: String {
37
+ switch self {
38
+ case .continue:
39
+ return "Continue"
40
+ case .initial:
41
+ return "Initial"
42
+ case .prepare:
43
+ return "Prepare"
44
+ case .execute:
45
+ return "Execute"
46
+ }
47
+ }
48
+ }
@@ -26,6 +26,7 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
26
26
  prototype.registerHybridMethod("updateManeuvers", &HybridMapTemplateSpec::updateManeuvers);
27
27
  prototype.registerHybridMethod("startNavigation", &HybridMapTemplateSpec::startNavigation);
28
28
  prototype.registerHybridMethod("stopNavigation", &HybridMapTemplateSpec::stopNavigation);
29
+ prototype.registerHybridMethod("setManeuverState", &HybridMapTemplateSpec::setManeuverState);
29
30
  });
30
31
  }
31
32
 
@@ -39,6 +39,8 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay { struct NitroMessag
39
39
  namespace margelo::nitro::swe::iternio::reactnativeautoplay { struct NitroLoadingManeuver; }
40
40
  // Forward declaration of `TripConfig` to properly resolve imports.
41
41
  namespace margelo::nitro::swe::iternio::reactnativeautoplay { struct TripConfig; }
42
+ // Forward declaration of `ManeuverState` to properly resolve imports.
43
+ namespace margelo::nitro::swe::iternio::reactnativeautoplay { enum class ManeuverState; }
42
44
 
43
45
  #include "MapTemplateConfig.hpp"
44
46
  #include <string>
@@ -59,6 +61,7 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay { struct TripConfig;
59
61
  #include "NitroLoadingManeuver.hpp"
60
62
  #include <variant>
61
63
  #include "TripConfig.hpp"
64
+ #include "ManeuverState.hpp"
62
65
 
63
66
  namespace margelo::nitro::swe::iternio::reactnativeautoplay {
64
67
 
@@ -103,6 +106,7 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
103
106
  virtual void updateManeuvers(const std::string& templateId, const std::variant<std::vector<NitroRoutingManeuver>, NitroMessageManeuver, NitroLoadingManeuver>& maneuvers) = 0;
104
107
  virtual void startNavigation(const std::string& templateId, const TripConfig& trip) = 0;
105
108
  virtual void stopNavigation(const std::string& templateId) = 0;
109
+ virtual void setManeuverState(const std::string& templateId, ManeuverState state) = 0;
106
110
 
107
111
  protected:
108
112
  // Hybrid Setup
@@ -0,0 +1,64 @@
1
+ ///
2
+ /// ManeuverState.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
+ #if __has_include(<NitroModules/JSIConverter.hpp>)
11
+ #include <NitroModules/JSIConverter.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+ #if __has_include(<NitroModules/NitroDefines.hpp>)
16
+ #include <NitroModules/NitroDefines.hpp>
17
+ #else
18
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19
+ #endif
20
+
21
+ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
22
+
23
+ /**
24
+ * An enum which can be represented as a JavaScript enum (ManeuverState).
25
+ */
26
+ enum class ManeuverState {
27
+ CONTINUE SWIFT_NAME(continue) = 0,
28
+ INITIAL SWIFT_NAME(initial) = 1,
29
+ PREPARE SWIFT_NAME(prepare) = 2,
30
+ EXECUTE SWIFT_NAME(execute) = 3,
31
+ } CLOSED_ENUM;
32
+
33
+ } // namespace margelo::nitro::swe::iternio::reactnativeautoplay
34
+
35
+ namespace margelo::nitro {
36
+
37
+ // C++ ManeuverState <> JS ManeuverState (enum)
38
+ template <>
39
+ struct JSIConverter<margelo::nitro::swe::iternio::reactnativeautoplay::ManeuverState> final {
40
+ static inline margelo::nitro::swe::iternio::reactnativeautoplay::ManeuverState fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
41
+ int enumValue = JSIConverter<int>::fromJSI(runtime, arg);
42
+ return static_cast<margelo::nitro::swe::iternio::reactnativeautoplay::ManeuverState>(enumValue);
43
+ }
44
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::swe::iternio::reactnativeautoplay::ManeuverState arg) {
45
+ int enumValue = static_cast<int>(arg);
46
+ return JSIConverter<int>::toJSI(runtime, enumValue);
47
+ }
48
+ static inline bool canConvert(jsi::Runtime&, const jsi::Value& value) {
49
+ if (!value.isNumber()) {
50
+ return false;
51
+ }
52
+ double number = value.getNumber();
53
+ int integer = static_cast<int>(number);
54
+ if (number != integer) {
55
+ // The integer is not the same value as the double - we truncated floating points.
56
+ // Enums are all integers, so the input floating point number is obviously invalid.
57
+ return false;
58
+ }
59
+ // Check if we are within the bounds of the enum.
60
+ return integer >= 0 && integer <= 3;
61
+ }
62
+ };
63
+
64
+ } // namespace margelo::nitro
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iternio/react-native-auto-play",
3
- "version": "0.3.8",
3
+ "version": "0.3.10",
4
4
  "description": "Android Auto and Apple CarPlay for react-native",
5
5
  "main": "lib/index",
6
6
  "module": "lib/index",
@@ -0,0 +1,37 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
3
+ import type { CleanupCallback } from '../types/Event';
4
+
5
+ type Props = { children: React.ReactNode; moduleName: string };
6
+
7
+ /**
8
+ * renders the passed children when the specified scene/screen appeared
9
+ * this makes sure child hooks are executed only when the map template is ready
10
+ */
11
+ export default function OnAppearedChildRenderer({ children, moduleName }: Props) {
12
+ const [didAppear, setDidAppear] = useState(false);
13
+
14
+ useEffect(() => {
15
+ let remove: CleanupCallback | null = HybridAutoPlay.addListenerRenderState(
16
+ moduleName,
17
+ (renderState) => {
18
+ if (renderState === 'didAppear') {
19
+ remove?.();
20
+ remove = null;
21
+ setDidAppear(true);
22
+ }
23
+ }
24
+ );
25
+
26
+ return () => {
27
+ remove?.();
28
+ remove = null;
29
+ };
30
+ }, [moduleName]);
31
+
32
+ if (didAppear) {
33
+ return children;
34
+ }
35
+
36
+ return null;
37
+ }
@@ -4,6 +4,7 @@ import type {
4
4
  TripSelectorCallback,
5
5
  VisibleTravelEstimate,
6
6
  } from '../templates/MapTemplate';
7
+ import type { ManeuverState } from '../types/Maneuver';
7
8
  import type { AutoText } from '../types/Text';
8
9
  import type {
9
10
  TripConfig,
@@ -48,4 +49,5 @@ export interface MapTemplate extends HybridObject<{ android: 'kotlin'; ios: 'swi
48
49
  updateManeuvers(templateId: string, maneuvers: NitroManeuver): void;
49
50
  startNavigation(templateId: string, trip: TripConfig): void;
50
51
  stopNavigation(templateId: string): void;
52
+ setManeuverState(templateId: string, state: ManeuverState): void;
51
53
  }
@@ -3,11 +3,12 @@ import { AppRegistry, Platform } from 'react-native';
3
3
  import { NitroModules } from 'react-native-nitro-modules';
4
4
  import type { AutoText } from '..';
5
5
  import { MapTemplateProvider } from '../components/MapTemplateContext';
6
+ import OnAppearedChildRenderer from '../components/OnAppearedChildRenderer';
6
7
  import { SafeAreaInsetsProvider } from '../components/SafeAreaInsetsContext';
7
8
  import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
8
9
  import type { MapTemplate as NitroMapTemplate } from '../specs/MapTemplate.nitro';
9
10
  import type { ActionButtonAndroid, MapButton, MapPanButton } from '../types/Button';
10
- import type { AutoManeuver } from '../types/Maneuver';
11
+ import type { AutoManeuver, ManeuverState } from '../types/Maneuver';
11
12
  import type { ColorScheme, RootComponentInitialProps } from '../types/RootComponent';
12
13
  import type {
13
14
  TripConfig,
@@ -180,7 +181,11 @@ export class MapTemplate extends Template<MapTemplateConfig, MapTemplateConfig['
180
181
  children: React.createElement(SafeAreaInsetsProvider, {
181
182
  moduleName: this.id,
182
183
  // biome-ignore lint/correctness/noChildrenProp: there is no other way in a ts file
183
- children: React.createElement(component, props),
184
+ children: React.createElement(OnAppearedChildRenderer, {
185
+ // biome-ignore lint/correctness/noChildrenProp: there is no other way in a ts file
186
+ children: React.createElement(component, props),
187
+ moduleName: this.id,
188
+ }),
184
189
  }),
185
190
  })
186
191
  );
@@ -341,4 +346,14 @@ export class MapTemplate extends Template<MapTemplateConfig, MapTemplateConfig['
341
346
  public stopNavigation() {
342
347
  HybridMapTemplate.stopNavigation(this.id);
343
348
  }
349
+
350
+ /**
351
+ * Sets the current maneuver state indicating progress within a maneuver.
352
+ * Transition through: continue → initial → prepare → execute → continue
353
+ * @namespace iOS sets CPManeuverState on the CPNavigationSession, used by instrument cluster and HUD
354
+ * @namespace Android no-op, Android Auto does not have an equivalent API
355
+ */
356
+ public setManeuverState(state: ManeuverState) {
357
+ HybridMapTemplate.setManeuverState(this.id, state);
358
+ }
344
359
  }
@@ -64,6 +64,19 @@ export enum KeepType {
64
64
  FollowRoad = 2,
65
65
  }
66
66
 
67
+ /**
68
+ * Describes the progress within a maneuver.
69
+ * Transition through: Continue → Initial → Prepare → Execute → Continue
70
+ * @namespace iOS sets CPManeuverState on the CPNavigationSession
71
+ * @namespace Android no-op, Android Auto does not have an equivalent API
72
+ */
73
+ export enum ManeuverState {
74
+ Continue = 0, // iOS .continue
75
+ Initial = 1, // iOS .initial
76
+ Prepare = 2, // iOS .prepare
77
+ Execute = 3, // iOS .execute
78
+ }
79
+
67
80
  export interface BaseManeuver {
68
81
  /**
69
82
  * @namespace iOS specify a unique identifier, sending over a Maneuver with a known id will only update the travelEstimates on the previously sent Maneuver
@@ -27,7 +27,7 @@ const convert = <T>(template: T, mapButtons?: MapButtons<T>): Array<NitroMapButt
27
27
  ? button.image.backgroundColor
28
28
  : 'transparent';
29
29
 
30
- const fontScale = (button.image.fontScale ?? Platform.OS === 'android') ? 1.0 : 0.65;
30
+ const fontScale = button.image.fontScale ?? (Platform.OS === 'android' ? 1.0 : 0.65);
31
31
 
32
32
  return {
33
33
  type,