@iternio/react-native-auto-play 0.0.5 → 0.0.7

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.
@@ -65,6 +65,8 @@ android {
65
65
 
66
66
  buildConfigField "float", "SCALE_FACTOR", getExtOrDefault("androidAutoScaleFactor")
67
67
  buildConfigField "long", "TELEMETRY_UPDATE_INTERVAL", getExtOrDefault("androidTelemetryUpdateInterval")
68
+ buildConfigField "long", "CLUSTER_SPLASH_DELAY_MS", getExtOrDefault("clusterSplashDelayMs")
69
+ buildConfigField "long", "CLUSTER_SPLASH_DURATION_MS", getExtOrDefault("clusterSplashDurationMs")
68
70
  }
69
71
 
70
72
  externalNativeBuild {
@@ -7,4 +7,6 @@ ReactNativeAutoPlay_ndkVersion=27.1.12297006
7
7
  ReactNativeAutoPlay_isAutomotiveApp=false
8
8
  # apply a scale factor on the root view that affects everything rendered by react-native, does not affect templates
9
9
  ReactNativeAutoPlay_androidAutoScaleFactor=1.5f
10
- ReactNativeAutoPlay_androidTelemetryUpdateInterval=4000
10
+ ReactNativeAutoPlay_androidTelemetryUpdateInterval=4000
11
+ ReactNativeAutoPlay_clusterSplashDelayMs=1000
12
+ ReactNativeAutoPlay_clusterSplashDurationMs=500
@@ -1,20 +1,31 @@
1
1
  package com.margelo.nitro.swe.iternio.reactnativeautoplay
2
2
 
3
+ import android.Manifest
3
4
  import android.annotation.SuppressLint
5
+ import android.app.Notification
6
+ import android.app.NotificationChannel
7
+ import android.app.NotificationManager
4
8
  import android.content.ComponentName
5
9
  import android.content.Intent
6
10
  import android.content.ServiceConnection
7
11
  import android.content.pm.ApplicationInfo
12
+ import android.content.pm.PackageManager
13
+ import android.graphics.Bitmap
8
14
  import android.os.IBinder
15
+ import android.util.Log
9
16
  import androidx.car.app.CarAppService
10
17
  import androidx.car.app.Session
11
18
  import androidx.car.app.SessionInfo
19
+ import androidx.car.app.notification.CarAppExtender
12
20
  import androidx.car.app.validation.HostValidator
21
+ import androidx.core.app.NotificationCompat
22
+ import androidx.core.app.NotificationManagerCompat
13
23
  import androidx.lifecycle.DefaultLifecycleObserver
14
24
  import androidx.lifecycle.LifecycleOwner
15
25
  import com.facebook.react.ReactApplication
16
26
  import com.facebook.react.bridge.LifecycleEventListener
17
27
  import com.facebook.react.bridge.ReactContext
28
+ import com.margelo.nitro.swe.iternio.reactnativeautoplay.utils.AppInfo
18
29
  import com.margelo.nitro.swe.iternio.reactnativeautoplay.utils.ReactContextResolver
19
30
  import kotlinx.coroutines.CoroutineScope
20
31
  import kotlinx.coroutines.Dispatchers
@@ -22,6 +33,7 @@ import kotlinx.coroutines.launch
22
33
 
23
34
  class AndroidAutoService : CarAppService() {
24
35
  private lateinit var reactContext: ReactContext
36
+ private lateinit var notificationManager: NotificationManager
25
37
 
26
38
  private var isServiceBound = false
27
39
  private var isSessionStarted = false
@@ -39,11 +51,21 @@ class AndroidAutoService : CarAppService() {
39
51
 
40
52
  override fun onCreate() {
41
53
  super.onCreate()
54
+ instance = this
42
55
 
43
56
  CoroutineScope(Dispatchers.Main).launch {
44
57
  reactContext = ReactContextResolver.getReactContext(application as ReactApplication)
45
58
  reactContext.addLifecycleEventListener(reactLifecycleObserver)
46
59
  }
60
+
61
+ notificationManager = getSystemService(NotificationManager::class.java)
62
+ val appLabel = AppInfo.getApplicationLabel(this)
63
+
64
+ getSystemService(NotificationManager::class.java).createNotificationChannel(
65
+ NotificationChannel(
66
+ CHANNEL_ID, appLabel, NotificationManager.IMPORTANCE_DEFAULT
67
+ )
68
+ )
47
69
  }
48
70
 
49
71
  override fun onCreateSession(sessionInfo: SessionInfo): Session {
@@ -60,6 +82,7 @@ class AndroidAutoService : CarAppService() {
60
82
 
61
83
  override fun onDestroy() {
62
84
  super.onDestroy()
85
+ instance = null
63
86
 
64
87
  stopForeground(STOP_FOREGROUND_REMOVE)
65
88
 
@@ -120,7 +143,61 @@ class AndroidAutoService : CarAppService() {
120
143
  }
121
144
  }
122
145
 
146
+ private fun createNotification(
147
+ title: String?, text: String?, largeIcon: Bitmap?
148
+ ): Notification {
149
+ return NotificationCompat.Builder(this, CHANNEL_ID)
150
+ .setSmallIcon(R.drawable.ic_notification).setOngoing(true)
151
+ .setCategory(NotificationCompat.CATEGORY_NAVIGATION).setOnlyAlertOnce(true)
152
+ .setWhen(System.currentTimeMillis()).setPriority(NotificationManager.IMPORTANCE_LOW)
153
+ .extend(
154
+ CarAppExtender.Builder().setImportance(NotificationManagerCompat.IMPORTANCE_LOW)
155
+ .build()
156
+ ).apply {
157
+ title?.let {
158
+ setContentTitle(it)
159
+ }
160
+ text?.let {
161
+ setContentText(it)
162
+ setTicker(it)
163
+ }
164
+ largeIcon?.let {
165
+ setLargeIcon(it)
166
+ }
167
+ }.build()
168
+ }
169
+
170
+ fun startForeground() {
171
+ val isLocationPermissionGranted =
172
+ checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED || checkSelfPermission(
173
+ Manifest.permission.ACCESS_FINE_LOCATION
174
+ ) == PackageManager.PERMISSION_GRANTED
175
+
176
+ if (!isLocationPermissionGranted) {
177
+ Log.w(TAG, "location permission not granted, unable to start foreground service!")
178
+ return
179
+ }
180
+
181
+ try {
182
+ startForeground(
183
+ NOTIFICATION_ID, createNotification(null, null, null)
184
+ )
185
+ } catch (e: SecurityException) {
186
+ Log.e(TAG, "failed to start foreground service", e)
187
+ }
188
+ }
189
+
190
+ fun notify(title: String?, text: String?, icon: Bitmap?) {
191
+ val notification = createNotification(title, text, icon)
192
+ notificationManager.notify(NOTIFICATION_ID, notification)
193
+ }
194
+
123
195
  companion object {
124
196
  const val TAG = "AndroidAutoService"
197
+ private const val NOTIFICATION_ID = 1
198
+ private const val CHANNEL_ID = "AutoPlayServiceChannel"
199
+
200
+ var instance: AndroidAutoService? = null
201
+ private set
125
202
  }
126
203
  }
@@ -28,7 +28,7 @@ class HybridCluster : HybridClusterSpec() {
28
28
  val carContext = AndroidAutoSession.getCarContext(clusterId)
29
29
  ?: throw IllegalArgumentException("initRootView failed, carContext for $clusterId cluster not found")
30
30
  val result = ThreadUtil.postOnUiAndAwait {
31
- VirtualRenderer(carContext, clusterId)
31
+ VirtualRenderer(carContext, clusterId, isCluster = true)
32
32
  }
33
33
  if (result.isFailure) {
34
34
  throw result.exceptionOrNull()
@@ -7,9 +7,12 @@ import android.graphics.Rect
7
7
  import android.hardware.display.DisplayManager
8
8
  import android.os.Bundle
9
9
  import android.view.Display
10
+ import android.view.LayoutInflater
10
11
  import android.view.View
11
12
  import android.view.ViewGroup
13
+ import android.view.ViewTreeObserver
12
14
  import android.widget.FrameLayout
15
+ import android.widget.TextView
13
16
  import androidx.car.app.AppManager
14
17
  import androidx.car.app.CarContext
15
18
  import androidx.car.app.SurfaceCallback
@@ -25,6 +28,7 @@ import com.facebook.react.uimanager.DisplayMetricsHolder
25
28
  import com.facebook.react.uimanager.UIManagerHelper
26
29
  import com.facebook.react.uimanager.common.UIManagerType
27
30
  import com.margelo.nitro.swe.iternio.reactnativeautoplay.template.AndroidAutoTemplate
31
+ import com.margelo.nitro.swe.iternio.reactnativeautoplay.utils.AppInfo
28
32
  import com.margelo.nitro.swe.iternio.reactnativeautoplay.utils.Debouncer
29
33
  import com.margelo.nitro.swe.iternio.reactnativeautoplay.utils.ReactContextResolver
30
34
  import kotlinx.coroutines.CoroutineScope
@@ -33,7 +37,9 @@ import kotlinx.coroutines.launch
33
37
  import kotlin.math.floor
34
38
 
35
39
  class VirtualRenderer(
36
- private val context: CarContext, private val moduleName: String
40
+ private val context: CarContext,
41
+ private val moduleName: String,
42
+ private val isCluster: Boolean = false
37
43
  ) {
38
44
  private lateinit var uiManager: FabricUIManager
39
45
  private lateinit var display: Display
@@ -48,6 +54,8 @@ class VirtualRenderer(
48
54
  private var height: Int = 0
49
55
  private var width: Int = 0
50
56
 
57
+ private var splashWillDisappear = false
58
+
51
59
  /**
52
60
  * scale is the actual scale factor required to calculate proper insets and is passed in initialProperties to js side
53
61
  */
@@ -55,7 +63,7 @@ class VirtualRenderer(
55
63
  val scale = BuildConfig.SCALE_FACTOR * virtualScreenDensity
56
64
 
57
65
  init {
58
- virtualRenderer.put(moduleName, this)
66
+ virtualRenderer[moduleName] = this
59
67
 
60
68
  CoroutineScope(Dispatchers.Main).launch {
61
69
  reactContext =
@@ -63,7 +71,7 @@ class VirtualRenderer(
63
71
 
64
72
  if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
65
73
  uiManager = UIManagerHelper.getUIManager(
66
- reactContext, UIManagerType.Companion.FABRIC
74
+ reactContext, UIManagerType.FABRIC
67
75
  ) as FabricUIManager
68
76
  }
69
77
 
@@ -188,7 +196,7 @@ class VirtualRenderer(
188
196
  val left = floor((visibleArea.left + additionalMarginLeft) / scale).toDouble()
189
197
  val right =
190
198
  floor((width - visibleArea.right + additionalMarginRight) / scale).toDouble()
191
- HybridAutoPlay.Companion.emitSafeAreaInsets(
199
+ HybridAutoPlay.emitSafeAreaInsets(
192
200
  moduleName = moduleName,
193
201
  top = top,
194
202
  bottom = bottom,
@@ -213,7 +221,7 @@ class VirtualRenderer(
213
221
  defaultMargin
214
222
  ) / scale
215
223
  ).toDouble()
216
- HybridAutoPlay.Companion.emitSafeAreaInsets(
224
+ HybridAutoPlay.emitSafeAreaInsets(
217
225
  moduleName = moduleName,
218
226
  top = top,
219
227
  bottom = bottom,
@@ -227,9 +235,9 @@ class VirtualRenderer(
227
235
  }
228
236
 
229
237
  private fun getMapTemplateConfig(): MapTemplateConfig? {
230
- val screenManager = AndroidAutoScreen.Companion.getScreen(moduleName)?.screenManager ?: return null
238
+ val screenManager = AndroidAutoScreen.getScreen(moduleName)?.screenManager ?: return null
231
239
  val marker = screenManager.top.marker ?: return null
232
- return AndroidAutoTemplate.Companion.getConfig(marker) as MapTemplateConfig?
240
+ return AndroidAutoTemplate.getConfig(marker) as MapTemplateConfig?
233
241
  }
234
242
 
235
243
  private fun initRenderer() {
@@ -283,12 +291,18 @@ class VirtualRenderer(
283
291
  override fun onCreate(savedInstanceState: Bundle?) {
284
292
  super.onCreate(savedInstanceState)
285
293
 
294
+ var splashScreenView: View? = null
295
+
286
296
  if (!this@VirtualRenderer::reactRootView.isInitialized) {
297
+ splashScreenView =
298
+ if (isCluster) getClusterSplashScreen(context, height, width) else null
299
+
287
300
  val instanceManager =
288
301
  (context.applicationContext as ReactApplication).reactNativeHost.reactInstanceManager
289
302
  reactRootView = ReactRootView(context.applicationContext).apply {
290
303
  layoutParams = FrameLayout.LayoutParams(
291
- (this@MapPresentation.width / reactNativeScale).toInt(), (this@MapPresentation.height / reactNativeScale).toInt()
304
+ (this@MapPresentation.width / reactNativeScale).toInt(),
305
+ (this@MapPresentation.height / reactNativeScale).toInt()
292
306
  )
293
307
  scaleX = reactNativeScale
294
308
  scaleY = reactNativeScale
@@ -296,6 +310,10 @@ class VirtualRenderer(
296
310
  pivotY = 0f
297
311
  setBackgroundColor(Color.DKGRAY)
298
312
 
313
+ splashScreenView?.let {
314
+ removeClusterSplashScreen({ viewTreeObserver }, it)
315
+ }
316
+
299
317
  startReactApplication(instanceManager, moduleName, initialProperties)
300
318
  runApplication()
301
319
  }
@@ -308,9 +326,13 @@ class VirtualRenderer(
308
326
  FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT
309
327
  )
310
328
  clipChildren = false
329
+
330
+ addView(reactRootView)
311
331
  }
312
332
 
313
- rootContainer.addView(reactRootView)
333
+ splashScreenView?.let {
334
+ rootContainer.addView(it)
335
+ }
314
336
 
315
337
  setContentView(rootContainer)
316
338
  }
@@ -331,7 +353,12 @@ class VirtualRenderer(
331
353
  reactSurfaceImpl = ReactSurfaceImpl(context, moduleName, initialProperties)
332
354
  }
333
355
 
356
+ var splashScreenView: View? = null
357
+
334
358
  if (!this@VirtualRenderer::reactSurfaceView.isInitialized) {
359
+ splashScreenView =
360
+ if (isCluster) getClusterSplashScreen(context, height, width) else null
361
+
335
362
  reactSurfaceView = ReactSurfaceView(context, reactSurfaceImpl).apply {
336
363
  layoutParams = FrameLayout.LayoutParams(
337
364
  (width / reactNativeScale).toInt(), (height / reactNativeScale).toInt()
@@ -341,6 +368,10 @@ class VirtualRenderer(
341
368
  pivotX = 0f
342
369
  pivotY = 0f
343
370
  setBackgroundColor(Color.DKGRAY)
371
+
372
+ splashScreenView?.let {
373
+ removeClusterSplashScreen({ viewTreeObserver }, it)
374
+ }
344
375
  }
345
376
 
346
377
  reactSurfaceId = uiManager.startSurface(
@@ -363,15 +394,61 @@ class VirtualRenderer(
363
394
  (reactSurfaceView.parent as ViewGroup).removeView(reactSurfaceView)
364
395
  }
365
396
 
366
- setContentView(FrameLayout(context).apply {
397
+ val rootContainer = FrameLayout(context).apply {
367
398
  layoutParams = FrameLayout.LayoutParams(
368
399
  FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT
369
400
  )
370
401
  clipChildren = false
371
402
 
372
403
  addView(reactSurfaceView)
373
- })
404
+ }
405
+
406
+ splashScreenView?.let {
407
+ rootContainer.addView(it)
408
+ }
409
+
410
+ setContentView(rootContainer)
411
+ }
412
+ }
413
+
414
+ private fun getClusterSplashScreen(
415
+ context: Context, containerHeight: Int, containerWidth: Int
416
+ ): View {
417
+ val layout =
418
+ LayoutInflater.from(context).inflate(R.layout.cluster_splashscreen, null, false)
419
+ val text = layout.findViewById<TextView>(R.id.splash_text)
420
+
421
+ AppInfo.getApplicationIcon(context)?.let {
422
+ val maxIconSize = minOf(64, (0.25 * maxOf(containerHeight, containerWidth)).toInt())
423
+
424
+ it.setBounds(0, 0, maxIconSize, maxIconSize)
425
+ text.setCompoundDrawables(null, it, null, null)
374
426
  }
427
+
428
+ text.text = AppInfo.getApplicationLabel(context)
429
+
430
+ return layout
431
+ }
432
+
433
+ private fun removeClusterSplashScreen(
434
+ getViewTreeObserver: () -> ViewTreeObserver, splashScreenView: View
435
+ ) {
436
+ getViewTreeObserver().addOnGlobalLayoutListener(object :
437
+ ViewTreeObserver.OnGlobalLayoutListener {
438
+ override fun onGlobalLayout() {
439
+ if (splashWillDisappear) {
440
+ return
441
+ }
442
+ splashWillDisappear = true
443
+
444
+ splashScreenView.animate().alpha(0f)
445
+ .setStartDelay(BuildConfig.CLUSTER_SPLASH_DELAY_MS)
446
+ .setDuration(BuildConfig.CLUSTER_SPLASH_DURATION_MS).withEndAction {
447
+ (splashScreenView.parent as? ViewGroup)?.removeView(splashScreenView)
448
+ getViewTreeObserver().removeOnGlobalLayoutListener(this)
449
+ }
450
+ }
451
+ })
375
452
  }
376
453
 
377
454
  companion object {
@@ -1,5 +1,6 @@
1
1
  package com.margelo.nitro.swe.iternio.reactnativeautoplay.template
2
2
 
3
+ import android.app.Service
3
4
  import android.graphics.Color
4
5
  import androidx.car.app.AppManager
5
6
  import androidx.car.app.CarContext
@@ -20,6 +21,7 @@ import com.facebook.react.bridge.UiThreadUtil
20
21
  import com.margelo.nitro.swe.iternio.reactnativeautoplay.AlertActionStyle
21
22
  import com.margelo.nitro.swe.iternio.reactnativeautoplay.AlertDismissalReason
22
23
  import com.margelo.nitro.swe.iternio.reactnativeautoplay.AndroidAutoScreen
24
+ import com.margelo.nitro.swe.iternio.reactnativeautoplay.AndroidAutoService
23
25
  import com.margelo.nitro.swe.iternio.reactnativeautoplay.AndroidAutoSession
24
26
  import com.margelo.nitro.swe.iternio.reactnativeautoplay.MapTemplateConfig
25
27
  import com.margelo.nitro.swe.iternio.reactnativeautoplay.NitroAction
@@ -262,6 +264,8 @@ class MapTemplate(
262
264
 
263
265
  updateTripDestinations()
264
266
  }
267
+
268
+ AndroidAutoService.instance?.startForeground()
265
269
  }
266
270
 
267
271
  fun updateTravelEstimates(steps: Array<TripPoint>) {
@@ -287,6 +291,8 @@ class MapTemplate(
287
291
  navigationInfo = null
288
292
 
289
293
  AndroidAutoScreen.invalidateSurfaceScreens()
294
+
295
+ AndroidAutoService.instance?.stopForeground(Service.STOP_FOREGROUND_REMOVE)
290
296
  }
291
297
 
292
298
  fun updateManeuvers(maneuvers: NitroManeuver) {
@@ -340,11 +346,29 @@ class MapTemplate(
340
346
  cardBackgroundColor = Parser.parseColor(backgroundColor)
341
347
 
342
348
  val currentStep = Parser.parseStep(context, current)
349
+ val currentDistance = Parser.parseDistance(current.travelEstimates.distanceRemaining)
350
+
343
351
  val nextStep = next?.let { Parser.parseStep(context, it) }
344
352
 
353
+ AndroidAutoService.instance?.let {
354
+ val notificationIcon = Parser.parseImageToBitmap(
355
+ context,
356
+ current.symbolImage.asFirstOrNull(),
357
+ current.symbolImage.asSecondOrNull()
358
+ )
359
+
360
+ val notificationText = currentStep.cue?.toString()
361
+
362
+ val notificationTitle = "${currentDistance.displayDistance.toInt()} ${Parser.parseDistanceUnit(currentDistance.displayUnit)}"
363
+
364
+ it.notify(
365
+ notificationTitle, notificationText, notificationIcon
366
+ )
367
+ }
368
+
345
369
  navigationInfo = RoutingInfo.Builder().apply {
346
370
  setCurrentStep(
347
- currentStep, Parser.parseDistance(current.travelEstimates.distanceRemaining)
371
+ currentStep, currentDistance
348
372
  )
349
373
  nextStep?.let { setNextStep(it) }
350
374
  }.build()
@@ -707,6 +707,17 @@ object Parser {
707
707
  }
708
708
  }
709
709
 
710
+ fun parseDistanceUnit(@Distance.Unit displayUnit: Int): String {
711
+ return when (displayUnit) {
712
+ Distance.UNIT_FEET -> "ft"
713
+ Distance.UNIT_KILOMETERS, Distance.UNIT_KILOMETERS_P1 -> "km"
714
+ Distance.UNIT_METERS -> "m"
715
+ Distance.UNIT_MILES, Distance.UNIT_MILES_P1 -> "mi"
716
+ Distance.UNIT_YARDS -> "yd"
717
+ else -> ""
718
+ }
719
+ }
720
+
710
721
  fun parseMapWithContentConfig(
711
722
  context: CarContext, mapConfig: NitroBaseMapTemplateConfig?, template: Template
712
723
  ): Template {
@@ -0,0 +1,7 @@
1
+ <vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="128dp" android:viewportHeight="192" android:viewportWidth="192" android:width="128dp">
2
+
3
+ <path android:fillColor="@android:color/transparent" android:pathData="M56,146H26.07c-3.11,0 -5.03,-3.4 -3.43,-6.06l69.93,-116.24c1.55,-2.58 5.3,-2.58 6.86,0l69.93,116.24c1.6,2.67 -0.32,6.06 -3.43,6.06H136" android:strokeColor="@android:color/white" android:strokeLineJoin="round" android:strokeWidth="12"/>
4
+
5
+ <path android:fillColor="@android:color/transparent" android:pathData="m42,170 l54,-92 54,92 -54,-24 -54,24Z" android:strokeColor="@android:color/white" android:strokeLineJoin="round" android:strokeWidth="12"/>
6
+
7
+ </vector>
@@ -0,0 +1,22 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
+ android:layout_width="match_parent"
4
+ android:layout_height="match_parent"
5
+ android:background="#444444"
6
+ android:gravity="center"
7
+ android:orientation="vertical">
8
+
9
+ <TextView
10
+ android:id="@+id/splash_text"
11
+ android:layout_width="match_parent"
12
+ android:layout_height="wrap_content"
13
+ android:drawableTop="@android:drawable/star_big_off"
14
+ android:drawablePadding="16sp"
15
+ android:gravity="center"
16
+ android:text="react-native-auto-play"
17
+ android:textColor="@android:color/white"
18
+ android:textSize="20sp"
19
+ android:textStyle="bold"
20
+ android:typeface="normal" />
21
+
22
+ </LinearLayout>
@@ -12,8 +12,6 @@ import CarPlay
12
12
  #endif
13
13
 
14
14
  class AutoPlayScene: UIResponder {
15
- public private(set) var state: VisibilityState = .diddisappear
16
-
17
15
  var initialProperties: [String: Any] = [:]
18
16
  var moduleName: String?
19
17
  var window: UIWindow?
@@ -75,16 +73,11 @@ class AutoPlayScene: UIResponder {
75
73
  }
76
74
 
77
75
  func setState(state: VisibilityState) {
78
- self.state = state
79
-
80
76
  guard let moduleName = self.moduleName else {
81
77
  return
82
78
  }
83
79
 
84
- HybridAutoPlay.emitRenderState(
85
- moduleName: moduleName,
86
- state: state
87
- )
80
+ SceneStore.setState(moduleName: moduleName, state: state)
88
81
  }
89
82
 
90
83
  func initRootView() {
@@ -10,6 +10,9 @@ import CarPlay
10
10
  class SceneStore {
11
11
  static let rootModuleName = "AutoPlayRoot"
12
12
  static let dashboardModuleName = "CarPlayDashboard"
13
+ static let windowSceneModuleName = "main"
14
+
15
+ private static var renderState = [String: VisibilityState]()
13
16
 
14
17
  private static var store: [String: AutoPlayScene] = [:]
15
18
 
@@ -34,7 +37,16 @@ class SceneStore {
34
37
  }
35
38
 
36
39
  static func getState(moduleName: String) -> VisibilityState? {
37
- return store[moduleName]?.state
40
+ return renderState[moduleName]
41
+ }
42
+
43
+ static func setState(moduleName: String, state: VisibilityState) {
44
+ renderState[moduleName] = state
45
+
46
+ HybridAutoPlay.emitRenderState(
47
+ moduleName: moduleName,
48
+ state: state
49
+ )
38
50
  }
39
51
 
40
52
  static func getDashboardScene() throws -> DashboardSceneDelegate? {
@@ -67,11 +79,11 @@ class SceneStore {
67
79
 
68
80
  return scene as? ClusterSceneDelegate
69
81
  }
70
-
82
+
71
83
  static func getRootScene() -> AutoPlayScene? {
72
84
  return store[SceneStore.rootModuleName]
73
85
  }
74
-
86
+
75
87
  static func getRootTraitCollection() -> UITraitCollection {
76
88
  return store[SceneStore.rootModuleName]!.traitCollection
77
89
  }
@@ -33,21 +33,30 @@ class WindowApplicationSceneDelegate: UIResponder, UIWindowSceneDelegate {
33
33
  }
34
34
 
35
35
  func sceneDidBecomeActive(_ scene: UIScene) {
36
- HybridAutoPlay.emitRenderState(moduleName: "main", state: .didappear)
36
+ SceneStore.setState(
37
+ moduleName: SceneStore.windowSceneModuleName,
38
+ state: .didappear
39
+ )
37
40
  }
38
41
 
39
42
  func sceneWillResignActive(_ scene: UIScene) {
40
- HybridAutoPlay.emitRenderState(
41
- moduleName: "main",
43
+ SceneStore.setState(
44
+ moduleName: SceneStore.windowSceneModuleName,
42
45
  state: .willdisappear
43
46
  )
44
47
  }
45
48
 
46
49
  func sceneWillEnterForeground(_ scene: UIScene) {
47
- HybridAutoPlay.emitRenderState(moduleName: "main", state: .willappear)
50
+ SceneStore.setState(
51
+ moduleName: SceneStore.windowSceneModuleName,
52
+ state: .willappear
53
+ )
48
54
  }
49
55
 
50
56
  func sceneDidEnterBackground(_ scene: UIScene) {
51
- HybridAutoPlay.emitRenderState(moduleName: "main", state: .diddisappear)
57
+ SceneStore.setState(
58
+ moduleName: SceneStore.windowSceneModuleName,
59
+ state: .diddisappear
60
+ )
52
61
  }
53
62
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iternio/react-native-auto-play",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "Android Auto and Apple CarPlay for react-native",
5
5
  "main": "lib/index",
6
6
  "module": "lib/index",