@iternio/react-native-auto-play 0.3.7 → 0.3.9
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.
- package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/AndroidAutoService.kt +4 -17
- package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/AndroidAutoSession.kt +21 -32
- package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridAutoPlay.kt +7 -0
- package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridCluster.kt +6 -0
- package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/VirtualRenderer.kt +64 -62
- package/ios/hybrid/HybridAutoPlay.swift +7 -0
- package/ios/hybrid/HybridCluster.swift +22 -8
- package/lib/AutoPlayHeadlessJsTask.d.ts +2 -1
- package/lib/AutoPlayHeadlessJsTask.js +4 -5
- package/lib/components/SafeAreaInsetsContext.d.ts +1 -1
- package/lib/components/SafeAreaInsetsContext.js +1 -1
- package/lib/hooks/useAndroidAutoTelemetry.js +2 -1
- package/lib/hooks/useFocusedEffect.js +1 -1
- package/lib/hooks/useVoiceInput.d.ts +1 -1
- package/lib/hooks/useVoiceInput.js +1 -1
- package/lib/hybrid/HybridAndroidAutoTelemetry.android.d.ts +2 -0
- package/lib/hybrid/HybridAndroidAutoTelemetry.android.js +2 -0
- package/lib/hybrid/HybridAndroidAutoTelemetry.d.ts +2 -0
- package/lib/hybrid/HybridAndroidAutoTelemetry.js +1 -0
- package/lib/hybrid/HybridAutoPlay.d.ts +2 -0
- package/lib/hybrid/HybridAutoPlay.js +2 -0
- package/lib/index.d.ts +4 -4
- package/lib/index.js +5 -5
- package/lib/scenes/CarPlayDashboardScene.d.ts +3 -3
- package/lib/scenes/CarPlayDashboardScene.js +1 -1
- package/lib/templates/MapTemplate.d.ts +1 -1
- package/lib/templates/MapTemplate.js +1 -1
- package/lib/templates/MessageTemplate.d.ts +1 -1
- package/lib/templates/MessageTemplate.js +1 -1
- package/lib/templates/Template.js +1 -1
- package/package.json +6 -4
- package/src/AutoPlayHeadlessJsTask.ts +12 -9
- package/src/components/SafeAreaInsetsContext.tsx +2 -1
- package/src/hooks/useAndroidAutoTelemetry.ts +2 -1
- package/src/hooks/useFocusedEffect.ts +1 -1
- package/src/hooks/useVoiceInput.ts +2 -1
- package/src/hybrid/HybridAndroidAutoTelemetry.android.ts +5 -0
- package/src/hybrid/HybridAndroidAutoTelemetry.ts +3 -0
- package/src/hybrid/HybridAutoPlay.ts +4 -0
- package/src/index.ts +5 -9
- package/src/scenes/CarPlayDashboardScene.ts +1 -1
- package/src/templates/MapTemplate.ts +2 -1
- package/src/templates/MessageTemplate.ts +7 -7
- package/src/templates/Template.ts +1 -1
- package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/utils/ReactContextResolver.kt +0 -36
|
@@ -23,17 +23,11 @@ import androidx.core.app.NotificationCompat
|
|
|
23
23
|
import androidx.core.app.NotificationManagerCompat
|
|
24
24
|
import androidx.lifecycle.DefaultLifecycleObserver
|
|
25
25
|
import androidx.lifecycle.LifecycleOwner
|
|
26
|
-
import com.facebook.react.ReactApplication
|
|
27
26
|
import com.facebook.react.bridge.LifecycleEventListener
|
|
28
|
-
import com.
|
|
27
|
+
import com.margelo.nitro.NitroModules
|
|
29
28
|
import com.margelo.nitro.swe.iternio.reactnativeautoplay.utils.AppInfo
|
|
30
|
-
import com.margelo.nitro.swe.iternio.reactnativeautoplay.utils.ReactContextResolver
|
|
31
|
-
import kotlinx.coroutines.CoroutineScope
|
|
32
|
-
import kotlinx.coroutines.Dispatchers
|
|
33
|
-
import kotlinx.coroutines.launch
|
|
34
29
|
|
|
35
30
|
class AndroidAutoService : CarAppService() {
|
|
36
|
-
private lateinit var reactContext: ReactContext
|
|
37
31
|
private lateinit var notificationManager: NotificationManager
|
|
38
32
|
|
|
39
33
|
private var isServiceBound = false
|
|
@@ -54,10 +48,7 @@ class AndroidAutoService : CarAppService() {
|
|
|
54
48
|
super.onCreate()
|
|
55
49
|
instance = this
|
|
56
50
|
|
|
57
|
-
|
|
58
|
-
reactContext = ReactContextResolver.getReactContext(application as ReactApplication)
|
|
59
|
-
reactContext.addLifecycleEventListener(reactLifecycleObserver)
|
|
60
|
-
}
|
|
51
|
+
NitroModules.applicationContext?.addLifecycleEventListener(reactLifecycleObserver)
|
|
61
52
|
|
|
62
53
|
notificationManager = getSystemService(NotificationManager::class.java)
|
|
63
54
|
val appLabel = AppInfo.getApplicationLabel(this)
|
|
@@ -72,7 +63,7 @@ class AndroidAutoService : CarAppService() {
|
|
|
72
63
|
}
|
|
73
64
|
|
|
74
65
|
override fun onCreateSession(sessionInfo: SessionInfo): Session {
|
|
75
|
-
val session = AndroidAutoSession(sessionInfo
|
|
66
|
+
val session = AndroidAutoSession(sessionInfo)
|
|
76
67
|
|
|
77
68
|
if (sessionInfo.displayType == SessionInfo.DISPLAY_TYPE_CLUSTER) {
|
|
78
69
|
return session
|
|
@@ -89,11 +80,7 @@ class AndroidAutoService : CarAppService() {
|
|
|
89
80
|
|
|
90
81
|
stopForeground(STOP_FOREGROUND_REMOVE)
|
|
91
82
|
|
|
92
|
-
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
reactContext.removeLifecycleEventListener(reactLifecycleObserver)
|
|
83
|
+
NitroModules.applicationContext?.removeLifecycleEventListener(reactLifecycleObserver)
|
|
97
84
|
}
|
|
98
85
|
|
|
99
86
|
private val reactLifecycleObserver = object : LifecycleEventListener {
|
|
@@ -12,21 +12,16 @@ import androidx.car.app.model.MessageTemplate
|
|
|
12
12
|
import androidx.car.app.model.Template
|
|
13
13
|
import androidx.lifecycle.DefaultLifecycleObserver
|
|
14
14
|
import androidx.lifecycle.LifecycleOwner
|
|
15
|
-
import com.facebook.react.ReactApplication
|
|
16
15
|
import com.facebook.react.bridge.LifecycleEventListener
|
|
17
|
-
import com.
|
|
16
|
+
import com.margelo.nitro.NitroModules
|
|
18
17
|
import com.margelo.nitro.swe.iternio.reactnativeautoplay.template.AndroidAutoTemplate
|
|
19
18
|
import com.margelo.nitro.swe.iternio.reactnativeautoplay.template.MapTemplate
|
|
20
19
|
import com.margelo.nitro.swe.iternio.reactnativeautoplay.utils.AppInfo
|
|
21
|
-
import com.margelo.nitro.swe.iternio.reactnativeautoplay.utils.ReactContextResolver
|
|
22
|
-
import kotlinx.coroutines.CoroutineScope
|
|
23
|
-
import kotlinx.coroutines.Dispatchers
|
|
24
|
-
import kotlinx.coroutines.launch
|
|
25
20
|
import java.util.UUID
|
|
26
21
|
import java.util.concurrent.ConcurrentHashMap
|
|
27
22
|
import java.util.concurrent.CopyOnWriteArrayList
|
|
28
23
|
|
|
29
|
-
class AndroidAutoSession(sessionInfo: SessionInfo
|
|
24
|
+
class AndroidAutoSession(sessionInfo: SessionInfo) :
|
|
30
25
|
Session() {
|
|
31
26
|
|
|
32
27
|
private val isCluster = sessionInfo.displayType == SessionInfo.DISPLAY_TYPE_CLUSTER
|
|
@@ -89,34 +84,29 @@ class AndroidAutoSession(sessionInfo: SessionInfo, private val reactApplication:
|
|
|
89
84
|
}
|
|
90
85
|
|
|
91
86
|
lifecycle.addObserver(sessionLifecycleObserver)
|
|
87
|
+
NitroModules.applicationContext?.addLifecycleEventListener(reactLifecycleObserver)
|
|
92
88
|
|
|
93
|
-
|
|
94
|
-
reactContext = ReactContextResolver.getReactContext(reactApplication)
|
|
95
|
-
reactContext.addLifecycleEventListener(reactLifecycleObserver)
|
|
96
|
-
|
|
97
|
-
// TODO this is not required for templates that host a component, check if we need this for non-rendering templates
|
|
98
|
-
/*
|
|
99
|
-
val appRegistry = reactContext.getJSModule(AppRegistry::class.java)
|
|
100
|
-
?: throw ClassNotFoundException("could not get AppRegistry instance")
|
|
101
|
-
val jsAppModuleName = if (isCluster) "AndroidAutoCluster" else "AndroidAuto"
|
|
102
|
-
val appParams = WritableNativeMap().apply {
|
|
103
|
-
putMap("initialProps", Arguments.createMap().apply {
|
|
104
|
-
putString("id", clusterTemplateId)
|
|
105
|
-
})
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
appRegistry.runApplication(jsAppModuleName, appParams)
|
|
109
|
-
*/
|
|
110
|
-
|
|
111
|
-
if (clusterId != null) {
|
|
112
|
-
HybridCluster.emit(ClusterEventName.DIDCONNECTWITHWINDOW, clusterId)
|
|
113
|
-
return@launch
|
|
114
|
-
}
|
|
115
|
-
|
|
89
|
+
if (clusterId == null) {
|
|
116
90
|
HybridAutoPlay.emit(EventName.DIDCONNECT)
|
|
91
|
+
} else {
|
|
92
|
+
HybridCluster.emit(ClusterEventName.DIDCONNECTWITHWINDOW, clusterId)
|
|
117
93
|
}
|
|
118
94
|
|
|
119
95
|
return screen
|
|
96
|
+
|
|
97
|
+
// TODO this is not required for templates that host a component, check if we need this for non-rendering templates
|
|
98
|
+
/*
|
|
99
|
+
val appRegistry = reactContext.getJSModule(AppRegistry::class.java)
|
|
100
|
+
?: throw ClassNotFoundException("could not get AppRegistry instance")
|
|
101
|
+
val jsAppModuleName = if (isCluster) "AndroidAutoCluster" else "AndroidAuto"
|
|
102
|
+
val appParams = WritableNativeMap().apply {
|
|
103
|
+
putMap("initialProps", Arguments.createMap().apply {
|
|
104
|
+
putString("id", clusterTemplateId)
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
appRegistry.runApplication(jsAppModuleName, appParams)
|
|
109
|
+
*/
|
|
120
110
|
}
|
|
121
111
|
|
|
122
112
|
override fun onCarConfigurationChanged(configuration: Configuration) {
|
|
@@ -129,7 +119,7 @@ class AndroidAutoSession(sessionInfo: SessionInfo, private val reactApplication:
|
|
|
129
119
|
}
|
|
130
120
|
|
|
131
121
|
val marker = AndroidAutoScreen.getScreen(ROOT_SESSION)?.marker ?: return
|
|
132
|
-
val config = AndroidAutoTemplate.getConfig(marker) as MapTemplateConfig? ?: return
|
|
122
|
+
val config = AndroidAutoTemplate.getConfig(marker) as? MapTemplateConfig? ?: return
|
|
133
123
|
|
|
134
124
|
if (config.onAppearanceDidChange != null) {
|
|
135
125
|
config.onAppearanceDidChange(colorScheme)
|
|
@@ -247,7 +237,6 @@ class AndroidAutoSession(sessionInfo: SessionInfo, private val reactApplication:
|
|
|
247
237
|
const val TAG = "AndroidAutoSession"
|
|
248
238
|
const val ROOT_SESSION = "AutoPlayRoot"
|
|
249
239
|
|
|
250
|
-
private lateinit var reactContext: ReactContext
|
|
251
240
|
private val sessions = ConcurrentHashMap<String, ScreenContext>()
|
|
252
241
|
|
|
253
242
|
private val clusterSessions = CopyOnWriteArrayList<String>()
|
package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridAutoPlay.kt
CHANGED
|
@@ -9,6 +9,13 @@ import java.util.concurrent.ConcurrentHashMap
|
|
|
9
9
|
import java.util.concurrent.CopyOnWriteArrayList
|
|
10
10
|
|
|
11
11
|
class HybridAutoPlay : HybridAutoPlaySpec() {
|
|
12
|
+
init {
|
|
13
|
+
listeners.clear()
|
|
14
|
+
renderStateListeners.clear()
|
|
15
|
+
voiceInputListeners.clear()
|
|
16
|
+
safeAreaInsetsListeners.clear()
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
override fun addListener(
|
|
13
20
|
eventType: EventName, callback: () -> Unit
|
|
14
21
|
): () -> Unit {
|
package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridCluster.kt
CHANGED
|
@@ -6,6 +6,12 @@ import java.util.concurrent.ConcurrentHashMap
|
|
|
6
6
|
import java.util.concurrent.CopyOnWriteArrayList
|
|
7
7
|
|
|
8
8
|
class HybridCluster : HybridClusterSpec() {
|
|
9
|
+
init {
|
|
10
|
+
listeners.clear()
|
|
11
|
+
eventQueue.clear()
|
|
12
|
+
colorSchemeListeners.clear()
|
|
13
|
+
}
|
|
14
|
+
|
|
9
15
|
override fun addListener(
|
|
10
16
|
eventType: ClusterEventName, callback: (String) -> Unit
|
|
11
17
|
): () -> Unit {
|
package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/VirtualRenderer.kt
CHANGED
|
@@ -2,12 +2,11 @@ package com.margelo.nitro.swe.iternio.reactnativeautoplay
|
|
|
2
2
|
|
|
3
3
|
import android.app.Presentation
|
|
4
4
|
import android.content.Context
|
|
5
|
-
import android.view.ContextThemeWrapper
|
|
6
5
|
import android.graphics.Color
|
|
7
6
|
import android.graphics.Rect
|
|
8
7
|
import android.hardware.display.DisplayManager
|
|
8
|
+
import android.hardware.display.VirtualDisplay
|
|
9
9
|
import android.os.Bundle
|
|
10
|
-
import android.util.Log
|
|
11
10
|
import android.view.Display
|
|
12
11
|
import android.view.LayoutInflater
|
|
13
12
|
import android.view.View
|
|
@@ -15,11 +14,11 @@ import android.view.ViewGroup
|
|
|
15
14
|
import android.view.ViewTreeObserver
|
|
16
15
|
import android.widget.FrameLayout
|
|
17
16
|
import android.widget.TextView
|
|
17
|
+
import androidx.annotation.MainThread
|
|
18
18
|
import androidx.car.app.AppManager
|
|
19
19
|
import androidx.car.app.CarContext
|
|
20
20
|
import androidx.car.app.SurfaceCallback
|
|
21
21
|
import androidx.car.app.SurfaceContainer
|
|
22
|
-
import com.facebook.react.ReactApplication
|
|
23
22
|
import com.facebook.react.bridge.Arguments
|
|
24
23
|
import com.facebook.react.bridge.ReactContext
|
|
25
24
|
import com.facebook.react.fabric.FabricUIManager
|
|
@@ -28,13 +27,11 @@ import com.facebook.react.runtime.ReactSurfaceView
|
|
|
28
27
|
import com.facebook.react.uimanager.DisplayMetricsHolder
|
|
29
28
|
import com.facebook.react.uimanager.UIManagerHelper
|
|
30
29
|
import com.facebook.react.uimanager.common.UIManagerType
|
|
30
|
+
import com.margelo.nitro.NitroModules
|
|
31
31
|
import com.margelo.nitro.swe.iternio.reactnativeautoplay.template.AndroidAutoTemplate
|
|
32
32
|
import com.margelo.nitro.swe.iternio.reactnativeautoplay.utils.AppInfo
|
|
33
33
|
import com.margelo.nitro.swe.iternio.reactnativeautoplay.utils.Debouncer
|
|
34
|
-
import
|
|
35
|
-
import kotlinx.coroutines.CoroutineScope
|
|
36
|
-
import kotlinx.coroutines.Dispatchers
|
|
37
|
-
import kotlinx.coroutines.launch
|
|
34
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
38
35
|
import kotlin.math.floor
|
|
39
36
|
|
|
40
37
|
class VirtualRenderer(
|
|
@@ -42,14 +39,7 @@ class VirtualRenderer(
|
|
|
42
39
|
private val moduleName: String,
|
|
43
40
|
private val isCluster: Boolean = false
|
|
44
41
|
) {
|
|
45
|
-
private
|
|
46
|
-
|
|
47
|
-
private fun isUiManagerInitialized(): Boolean {
|
|
48
|
-
return ::fabricUiManager.isInitialized
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
private lateinit var display: Display
|
|
52
|
-
private lateinit var reactContext: ReactContext
|
|
42
|
+
private var virtualDisplay: VirtualDisplay? = null
|
|
53
43
|
|
|
54
44
|
private lateinit var reactSurfaceImpl: ReactSurfaceImpl
|
|
55
45
|
private var reactSurfaceView: ReactSurfaceView? = null
|
|
@@ -66,20 +56,13 @@ class VirtualRenderer(
|
|
|
66
56
|
private val virtualScreenDensity = context.resources.displayMetrics.density
|
|
67
57
|
val scale = BuildConfig.SCALE_FACTOR * virtualScreenDensity
|
|
68
58
|
|
|
59
|
+
private fun isSurfaceReady(surfaceContainer: SurfaceContainer): Boolean {
|
|
60
|
+
return surfaceContainer.surface != null && surfaceContainer.dpi != 0 && surfaceContainer.height != 0 && surfaceContainer.width != 0
|
|
61
|
+
}
|
|
62
|
+
|
|
69
63
|
init {
|
|
70
64
|
virtualRenderer[moduleName] = this
|
|
71
65
|
|
|
72
|
-
CoroutineScope(Dispatchers.Main).launch {
|
|
73
|
-
reactContext =
|
|
74
|
-
ReactContextResolver.getReactContext(context.applicationContext as ReactApplication)
|
|
75
|
-
|
|
76
|
-
fabricUiManager = UIManagerHelper.getUIManager(
|
|
77
|
-
reactContext, UIManagerType.FABRIC
|
|
78
|
-
) as FabricUIManager
|
|
79
|
-
|
|
80
|
-
initRenderer()
|
|
81
|
-
}
|
|
82
|
-
|
|
83
66
|
context.getCarService(AppManager::class.java).setSurfaceCallback(object : SurfaceCallback {
|
|
84
67
|
val areaDebouncer = Debouncer(200)
|
|
85
68
|
|
|
@@ -90,13 +73,12 @@ class VirtualRenderer(
|
|
|
90
73
|
var visibleArea = Rect(0, 0, 0, 0)
|
|
91
74
|
|
|
92
75
|
override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) {
|
|
93
|
-
if (surfaceContainer
|
|
94
|
-
Log.w(TAG, "surface is null")
|
|
76
|
+
if (!isSurfaceReady(surfaceContainer)) {
|
|
95
77
|
return
|
|
96
78
|
}
|
|
97
79
|
|
|
98
80
|
val manager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
|
|
99
|
-
|
|
81
|
+
virtualDisplay = manager.createVirtualDisplay(
|
|
100
82
|
moduleName,
|
|
101
83
|
surfaceContainer.width,
|
|
102
84
|
surfaceContainer.height,
|
|
@@ -105,11 +87,16 @@ class VirtualRenderer(
|
|
|
105
87
|
DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION,
|
|
106
88
|
)
|
|
107
89
|
|
|
108
|
-
display = virtualDisplay
|
|
90
|
+
val display = virtualDisplay?.display ?: return
|
|
109
91
|
height = surfaceContainer.height
|
|
110
92
|
width = surfaceContainer.width
|
|
111
93
|
|
|
112
|
-
initRenderer()
|
|
94
|
+
initRenderer(display)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) {
|
|
98
|
+
virtualDisplay?.release()
|
|
99
|
+
virtualDisplay = null
|
|
113
100
|
}
|
|
114
101
|
|
|
115
102
|
override fun onScroll(distanceX: Float, distanceY: Float) {
|
|
@@ -247,10 +234,12 @@ class VirtualRenderer(
|
|
|
247
234
|
return AndroidAutoTemplate.getTypedConfig<MapTemplateConfig>(marker)
|
|
248
235
|
}
|
|
249
236
|
|
|
250
|
-
private fun initRenderer() {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
237
|
+
private fun initRenderer(display: Display) {
|
|
238
|
+
val reactContext = NitroModules.applicationContext ?: return
|
|
239
|
+
|
|
240
|
+
val fabricUiManager = UIManagerHelper.getUIManager(
|
|
241
|
+
reactContext, UIManagerType.FABRIC
|
|
242
|
+
) as? FabricUIManager? ?: return
|
|
254
243
|
|
|
255
244
|
val initialProperties = Bundle().apply {
|
|
256
245
|
putString("id", moduleName)
|
|
@@ -270,20 +259,21 @@ class VirtualRenderer(
|
|
|
270
259
|
val mainScreenDensity = DisplayMetricsHolder.getScreenDisplayMetrics().density
|
|
271
260
|
val reactNativeScale = virtualScreenDensity / mainScreenDensity * BuildConfig.SCALE_FACTOR
|
|
272
261
|
|
|
273
|
-
if (!isUiManagerInitialized()) {
|
|
274
|
-
// this makes sure we have all required instances
|
|
275
|
-
// no matter if the app is launched on the phone or AA first
|
|
276
|
-
return
|
|
277
|
-
}
|
|
278
|
-
|
|
279
262
|
FabricMapPresentation(
|
|
280
|
-
|
|
263
|
+
reactContext,
|
|
264
|
+
display,
|
|
265
|
+
fabricUiManager,
|
|
266
|
+
height,
|
|
267
|
+
width,
|
|
268
|
+
initialProperties,
|
|
269
|
+
reactNativeScale
|
|
281
270
|
).show()
|
|
282
271
|
}
|
|
283
272
|
|
|
284
273
|
inner class FabricMapPresentation(
|
|
285
|
-
private val context:
|
|
274
|
+
private val context: ReactContext,
|
|
286
275
|
display: Display,
|
|
276
|
+
private val fabricUiManager: FabricUIManager,
|
|
287
277
|
private val height: Int,
|
|
288
278
|
private val width: Int,
|
|
289
279
|
private val initialProperties: Bundle,
|
|
@@ -292,11 +282,8 @@ class VirtualRenderer(
|
|
|
292
282
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
293
283
|
super.onCreate(savedInstanceState)
|
|
294
284
|
|
|
295
|
-
val appTheme = context.applicationContext.applicationInfo.theme
|
|
296
|
-
val themedContext = ContextThemeWrapper(context.applicationContext, appTheme)
|
|
297
|
-
|
|
298
285
|
if (!this@VirtualRenderer::reactSurfaceImpl.isInitialized) {
|
|
299
|
-
reactSurfaceImpl = ReactSurfaceImpl(
|
|
286
|
+
reactSurfaceImpl = ReactSurfaceImpl(context, moduleName, initialProperties)
|
|
300
287
|
}
|
|
301
288
|
|
|
302
289
|
var splashScreenView: View? = null
|
|
@@ -305,9 +292,9 @@ class VirtualRenderer(
|
|
|
305
292
|
(it.parent as ViewGroup).removeView(it)
|
|
306
293
|
} ?: run {
|
|
307
294
|
splashScreenView =
|
|
308
|
-
if (isCluster) getClusterSplashScreen(
|
|
295
|
+
if (isCluster) getClusterSplashScreen(context, height, width) else null
|
|
309
296
|
|
|
310
|
-
val surfaceView = ReactSurfaceView(
|
|
297
|
+
val surfaceView = ReactSurfaceView(context, reactSurfaceImpl).apply {
|
|
311
298
|
layoutParams = FrameLayout.LayoutParams(
|
|
312
299
|
(width / reactNativeScale).toInt(), (height / reactNativeScale).toInt()
|
|
313
300
|
)
|
|
@@ -335,7 +322,7 @@ class VirtualRenderer(
|
|
|
335
322
|
)
|
|
336
323
|
|
|
337
324
|
// remove ui-managers lifecycle listener to not stop rendering when app is not in foreground/phone screen is off
|
|
338
|
-
|
|
325
|
+
context.removeLifecycleEventListener(fabricUiManager)
|
|
339
326
|
// trigger ui-managers onHostResume to make sure the surface is rendered properly even when AA only is starting without the phone app
|
|
340
327
|
fabricUiManager.onHostResume()
|
|
341
328
|
|
|
@@ -343,7 +330,7 @@ class VirtualRenderer(
|
|
|
343
330
|
}
|
|
344
331
|
|
|
345
332
|
|
|
346
|
-
val rootContainer = FrameLayout(
|
|
333
|
+
val rootContainer = FrameLayout(context).apply {
|
|
347
334
|
layoutParams = FrameLayout.LayoutParams(
|
|
348
335
|
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT
|
|
349
336
|
)
|
|
@@ -365,8 +352,7 @@ class VirtualRenderer(
|
|
|
365
352
|
): View {
|
|
366
353
|
val root = FrameLayout(context).apply {
|
|
367
354
|
layoutParams = ViewGroup.LayoutParams(
|
|
368
|
-
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
369
|
-
ViewGroup.LayoutParams.MATCH_PARENT
|
|
355
|
+
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
|
|
370
356
|
)
|
|
371
357
|
}
|
|
372
358
|
|
|
@@ -407,24 +393,40 @@ class VirtualRenderer(
|
|
|
407
393
|
})
|
|
408
394
|
}
|
|
409
395
|
|
|
396
|
+
@MainThread
|
|
397
|
+
private fun stop() {
|
|
398
|
+
virtualDisplay?.release()
|
|
399
|
+
virtualDisplay = null
|
|
400
|
+
|
|
401
|
+
val uiManager = NitroModules.applicationContext?.let {
|
|
402
|
+
UIManagerHelper.getUIManager(
|
|
403
|
+
it, UIManagerType.FABRIC
|
|
404
|
+
) as? FabricUIManager?
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
try {
|
|
408
|
+
reactSurfaceId?.let {
|
|
409
|
+
uiManager?.stopSurface(it)
|
|
410
|
+
}
|
|
411
|
+
} catch (_: AssertionError) {
|
|
412
|
+
// Fabric already invalidated
|
|
413
|
+
} finally {
|
|
414
|
+
reactSurfaceId = null
|
|
415
|
+
virtualRenderer.remove(moduleName)
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
410
419
|
companion object {
|
|
411
420
|
const val TAG = "VirtualRenderer"
|
|
412
421
|
|
|
413
|
-
private val virtualRenderer =
|
|
422
|
+
private val virtualRenderer = ConcurrentHashMap<String, VirtualRenderer>()
|
|
414
423
|
|
|
415
424
|
fun hasRenderer(moduleId: String): Boolean {
|
|
416
425
|
return virtualRenderer.contains(moduleId)
|
|
417
426
|
}
|
|
418
427
|
|
|
419
428
|
fun removeRenderer(moduleId: String) {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
if (renderer?.isUiManagerInitialized() == true) {
|
|
423
|
-
renderer.reactSurfaceId?.let {
|
|
424
|
-
renderer.fabricUiManager.stopSurface(it)
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
429
|
+
virtualRenderer[moduleId]?.stop()
|
|
428
430
|
virtualRenderer.remove(moduleId)
|
|
429
431
|
}
|
|
430
432
|
}
|
|
@@ -21,6 +21,13 @@ class HybridAutoPlay: HybridAutoPlaySpec {
|
|
|
21
21
|
private static var renderStateListeners = [String: [RenderStateListener]]()
|
|
22
22
|
private static var safeAreaInsetsListeners = [String: [SafeAreaListener]]()
|
|
23
23
|
|
|
24
|
+
override init() {
|
|
25
|
+
HybridAutoPlay.listeners.removeAll()
|
|
26
|
+
HybridAutoPlay.renderStateListeners.removeAll()
|
|
27
|
+
HybridAutoPlay.safeAreaInsetsListeners.removeAll()
|
|
28
|
+
super.init()
|
|
29
|
+
}
|
|
30
|
+
|
|
24
31
|
func addListener(eventType: EventName, callback: @escaping () -> Void)
|
|
25
32
|
throws -> () -> Void
|
|
26
33
|
{
|
|
@@ -31,6 +31,16 @@ class HybridCluster: HybridClusterSpec {
|
|
|
31
31
|
String: (_: String, _: Bool) -> Void
|
|
32
32
|
]()
|
|
33
33
|
|
|
34
|
+
override init() {
|
|
35
|
+
HybridCluster.listeners.removeAll()
|
|
36
|
+
HybridCluster.eventQueue.removeAll()
|
|
37
|
+
HybridCluster.colorSchemeListeners.removeAll()
|
|
38
|
+
HybridCluster.zoomListeners.removeAll()
|
|
39
|
+
HybridCluster.compassListeners.removeAll()
|
|
40
|
+
HybridCluster.speedLimitListeners.removeAll()
|
|
41
|
+
super.init()
|
|
42
|
+
}
|
|
43
|
+
|
|
34
44
|
func addListener(
|
|
35
45
|
eventType: ClusterEventName,
|
|
36
46
|
callback: @escaping (_ clusterId: String) -> Void
|
|
@@ -57,12 +67,14 @@ class HybridCluster: HybridClusterSpec {
|
|
|
57
67
|
return Promise.async {
|
|
58
68
|
if #available(iOS 15.4, *) {
|
|
59
69
|
try await MainActor.run {
|
|
60
|
-
guard
|
|
61
|
-
|
|
62
|
-
|
|
70
|
+
guard
|
|
71
|
+
let scene = SceneStore.getClusterScene(
|
|
72
|
+
clusterId: clusterId
|
|
73
|
+
)
|
|
74
|
+
else {
|
|
63
75
|
return
|
|
64
76
|
}
|
|
65
|
-
|
|
77
|
+
|
|
66
78
|
try scene.initRootView()
|
|
67
79
|
}
|
|
68
80
|
}
|
|
@@ -80,12 +92,14 @@ class HybridCluster: HybridClusterSpec {
|
|
|
80
92
|
[NitroAttributedString]
|
|
81
93
|
) throws {
|
|
82
94
|
if #available(iOS 15.4, *) {
|
|
83
|
-
guard
|
|
84
|
-
|
|
85
|
-
|
|
95
|
+
guard
|
|
96
|
+
let scene = SceneStore.getClusterScene(
|
|
97
|
+
clusterId: clusterId
|
|
98
|
+
)
|
|
99
|
+
else {
|
|
86
100
|
return
|
|
87
101
|
}
|
|
88
|
-
|
|
102
|
+
|
|
89
103
|
scene.setAttributedInactiveDescriptionVariants(
|
|
90
104
|
attributedInactiveDescriptionVariants:
|
|
91
105
|
attributedInactiveDescriptionVariants
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { AppRegistry, Platform } from 'react-native';
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const remove = HybridAutoPlay.addListener('didDisconnect', () => {
|
|
2
|
+
const createTaskProvider = (hybridAutoPlay) => () => () => new Promise((resolve) => {
|
|
3
|
+
const remove = hybridAutoPlay.addListener('didDisconnect', () => {
|
|
5
4
|
resolve();
|
|
6
5
|
remove();
|
|
7
6
|
});
|
|
8
7
|
});
|
|
9
|
-
const registerHeadlessTask = () => {
|
|
8
|
+
const registerHeadlessTask = (hybridAutoPlay) => {
|
|
10
9
|
if (Platform.OS !== 'android') {
|
|
11
10
|
return;
|
|
12
11
|
}
|
|
13
|
-
AppRegistry.registerHeadlessTask('AndroidAutoHeadlessJsTask',
|
|
12
|
+
AppRegistry.registerHeadlessTask('AndroidAutoHeadlessJsTask', createTaskProvider(hybridAutoPlay));
|
|
14
13
|
};
|
|
15
14
|
export default { registerHeadlessTask };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import type { SafeAreaInsets } from '..';
|
|
3
3
|
export declare const SafeAreaInsetsContext: React.Context<SafeAreaInsets>;
|
|
4
4
|
export declare function SafeAreaInsetsProvider({ children, moduleName, }: {
|
|
5
5
|
children: React.ReactNode;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, useEffect, useState } from 'react';
|
|
3
|
-
import { HybridAutoPlay } from '
|
|
3
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
4
4
|
const DEFAULT = { top: 0, bottom: 0, left: 0, right: 0 };
|
|
5
5
|
export const SafeAreaInsetsContext = createContext(DEFAULT);
|
|
6
6
|
export function SafeAreaInsetsProvider({ children, moduleName, }) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
2
|
import { PermissionsAndroid } from 'react-native';
|
|
3
|
-
import { HybridAndroidAutoTelemetry
|
|
3
|
+
import { HybridAndroidAutoTelemetry } from '../hybrid/HybridAndroidAutoTelemetry';
|
|
4
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
4
5
|
/**
|
|
5
6
|
* Hook to check if the telemetry permissions are granted. If the permissions are not granted, it will request them from the user.
|
|
6
7
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { HybridAutoPlay } from '
|
|
2
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
3
3
|
/**
|
|
4
4
|
* An effect hook that only runs when the CarPlay/Android Auto screen is visible to the user and dependencies have changed.
|
|
5
5
|
* It behaves like `useEffect`, but the effect function is only executed if the screen is visible.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
-
import { HybridAutoPlay } from '
|
|
2
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
3
3
|
export const useVoiceInput = () => {
|
|
4
4
|
const [isConnected, setIsConnected] = useState(false);
|
|
5
5
|
const [voiceInputResult, setVoiceInputResult] = useState();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const HybridAndroidAutoTelemetry = null;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { HybridAndroidAutoTelemetry } from './hybrid/HybridAndroidAutoTelemetry';
|
|
2
|
+
import { HybridAutoPlay } from './hybrid/HybridAutoPlay';
|
|
1
3
|
import type { AndroidAutomotive } from './specs/AndroidAutomotive.nitro';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export declare const HybridAutoPlay: NitroAutoPlay;
|
|
5
|
-
export declare const HybridAndroidAutoTelemetry: NitroAndroidAutoTelemetry | null;
|
|
4
|
+
export { HybridAutoPlay };
|
|
5
|
+
export { HybridAndroidAutoTelemetry };
|
|
6
6
|
export declare const HybridAndroidAutomotive: AndroidAutomotive | null;
|
|
7
7
|
/**
|
|
8
8
|
* These are the static module names for the app running on the mobile device, head unit screen and the CarPlay dashboard.
|
package/lib/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Platform } from 'react-native';
|
|
2
2
|
import { NitroModules } from 'react-native-nitro-modules';
|
|
3
3
|
import AutoPlayHeadlessJsTask from './AutoPlayHeadlessJsTask';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import { HybridAndroidAutoTelemetry } from './hybrid/HybridAndroidAutoTelemetry';
|
|
5
|
+
import { HybridAutoPlay } from './hybrid/HybridAutoPlay';
|
|
6
|
+
AutoPlayHeadlessJsTask.registerHeadlessTask(HybridAutoPlay);
|
|
7
|
+
export { HybridAutoPlay };
|
|
8
|
+
export { HybridAndroidAutoTelemetry };
|
|
9
9
|
export const HybridAndroidAutomotive = Platform.OS === 'android'
|
|
10
10
|
? NitroModules.createHybridObject('AndroidAutomotive')
|
|
11
11
|
: null;
|
|
@@ -27,9 +27,9 @@ declare class Dashboard {
|
|
|
27
27
|
* @param eventType generic events
|
|
28
28
|
* @returns callback to remove the listener
|
|
29
29
|
*/
|
|
30
|
-
addListener(event: EventName, callback: () => void): import("
|
|
31
|
-
addListenerRenderState(callback: (payload: VisibilityState) => void): import("
|
|
32
|
-
addListenerColorScheme(callback: (payload: ColorScheme) => void): import("
|
|
30
|
+
addListener(event: EventName, callback: () => void): import("../types/Event").CleanupCallback;
|
|
31
|
+
addListenerRenderState(callback: (payload: VisibilityState) => void): import("../types/Event").CleanupCallback;
|
|
32
|
+
addListenerColorScheme(callback: (payload: ColorScheme) => void): import("../types/Event").CleanupCallback;
|
|
33
33
|
}
|
|
34
34
|
export declare const CarPlayDashboard: Dashboard;
|
|
35
35
|
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { AppRegistry, Platform } from 'react-native';
|
|
3
3
|
import { NitroModules } from 'react-native-nitro-modules';
|
|
4
|
-
import { HybridAutoPlay } from '..';
|
|
5
4
|
import { SafeAreaInsetsProvider } from '../components/SafeAreaInsetsContext';
|
|
5
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
6
6
|
import { NitroImageUtil } from '../utils/NitroImage';
|
|
7
7
|
const HybridCarPlayDashboard = Platform.OS === 'ios'
|
|
8
8
|
? NitroModules.createHybridObject('CarPlayDashboard')
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import type { AutoText } from '..';
|
|
3
3
|
import type { ActionButtonAndroid, MapButton, MapPanButton } from '../types/Button';
|
|
4
4
|
import type { AutoManeuver } from '../types/Maneuver';
|
|
5
5
|
import type { ColorScheme, RootComponentInitialProps } from '../types/RootComponent';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { AppRegistry, Platform } from 'react-native';
|
|
3
3
|
import { NitroModules } from 'react-native-nitro-modules';
|
|
4
|
-
import { HybridAutoPlay } from '..';
|
|
5
4
|
import { MapTemplateProvider } from '../components/MapTemplateContext';
|
|
6
5
|
import { SafeAreaInsetsProvider } from '../components/SafeAreaInsetsContext';
|
|
6
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
7
7
|
import { NitroActionUtil } from '../utils/NitroAction';
|
|
8
8
|
import { NitroAlertUtil } from '../utils/NitroAlert';
|
|
9
9
|
import { NitroManeuverUtil } from '../utils/NitroManeuver';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AutoImage, BaseMapTemplateConfig, CustomActionButtonAndroid, HeaderActionsAndroid, TextButton } from '..';
|
|
2
2
|
import type { AutoText } from '../types/Text';
|
|
3
3
|
import { type NitroAction } from '../utils/NitroAction';
|
|
4
4
|
import { type NitroImage } from '../utils/NitroImage';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Platform } from 'react-native';
|
|
2
2
|
import { NitroModules } from 'react-native-nitro-modules';
|
|
3
3
|
import uuid from 'react-native-uuid';
|
|
4
|
-
import { HybridAutoPlay
|
|
4
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
5
5
|
import { NitroActionUtil } from '../utils/NitroAction';
|
|
6
6
|
import { NitroImageUtil } from '../utils/NitroImage';
|
|
7
7
|
import { NitroMapButton } from '../utils/NitroMapButton';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iternio/react-native-auto-play",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
4
4
|
"description": "Android Auto and Apple CarPlay for react-native",
|
|
5
5
|
"main": "lib/index",
|
|
6
6
|
"module": "lib/index",
|
|
@@ -36,8 +36,9 @@
|
|
|
36
36
|
"typescript": "tsc",
|
|
37
37
|
"generate:fonts": "node ./assets/symbolFont/bundleAsset.js",
|
|
38
38
|
"specs": "nitrogen --logLevel=\"debug\"",
|
|
39
|
-
"prepare": "tsc && nitrogen && npm run generate:fonts",
|
|
40
|
-
"swift:format": "swift-format format ./ios --in-place --recursive"
|
|
39
|
+
"prepare": "yarn circular && tsc && nitrogen && npm run generate:fonts",
|
|
40
|
+
"swift:format": "swift-format format ./ios --in-place --recursive",
|
|
41
|
+
"circular": "dpdm ./src/* --circular --exit-code circular:1 --no-tree --warning=false --transform"
|
|
41
42
|
},
|
|
42
43
|
"keywords": [
|
|
43
44
|
"react-native",
|
|
@@ -59,7 +60,8 @@
|
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
61
62
|
"@types/jest": "^29.5.12",
|
|
62
|
-
"@types/react": "
|
|
63
|
+
"@types/react": "~19.2.0",
|
|
64
|
+
"dpdm": "^4.0.1",
|
|
63
65
|
"nitrogen": "^0.35.3",
|
|
64
66
|
"typescript": "^5.8.3"
|
|
65
67
|
},
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { AppRegistry, Platform, type Task, type TaskProvider } from 'react-native';
|
|
2
|
-
import {
|
|
2
|
+
import type { AutoPlay as NitroAutoPlay } from './specs/AutoPlay.nitro';
|
|
3
3
|
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
const createTaskProvider =
|
|
5
|
+
(hybridAutoPlay: NitroAutoPlay): TaskProvider =>
|
|
6
|
+
(): Task =>
|
|
7
|
+
() =>
|
|
8
|
+
new Promise((resolve) => {
|
|
9
|
+
const remove = hybridAutoPlay.addListener('didDisconnect', () => {
|
|
10
|
+
resolve();
|
|
11
|
+
remove();
|
|
12
|
+
});
|
|
9
13
|
});
|
|
10
|
-
});
|
|
11
14
|
|
|
12
|
-
const registerHeadlessTask = () => {
|
|
15
|
+
const registerHeadlessTask = (hybridAutoPlay: NitroAutoPlay) => {
|
|
13
16
|
if (Platform.OS !== 'android') {
|
|
14
17
|
return;
|
|
15
18
|
}
|
|
16
|
-
AppRegistry.registerHeadlessTask('AndroidAutoHeadlessJsTask',
|
|
19
|
+
AppRegistry.registerHeadlessTask('AndroidAutoHeadlessJsTask', createTaskProvider(hybridAutoPlay));
|
|
17
20
|
};
|
|
18
21
|
|
|
19
22
|
export default { registerHeadlessTask };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import { createContext, useEffect, useState } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import type { SafeAreaInsets } from '..';
|
|
4
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
4
5
|
|
|
5
6
|
const DEFAULT: SafeAreaInsets = { top: 0, bottom: 0, left: 0, right: 0 };
|
|
6
7
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
2
|
import { type Permission, PermissionsAndroid } from 'react-native';
|
|
3
|
-
import { HybridAndroidAutoTelemetry
|
|
3
|
+
import { HybridAndroidAutoTelemetry } from '../hybrid/HybridAndroidAutoTelemetry';
|
|
4
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
4
5
|
|
|
5
6
|
import type { AndroidAutoPermissions, Telemetry } from '../types/Telemetry';
|
|
6
7
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { HybridAutoPlay } from '
|
|
2
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* An effect hook that only runs when the CarPlay/Android Auto screen is visible to the user and dependencies have changed.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import type { Location } from '..';
|
|
3
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
3
4
|
|
|
4
5
|
export const useVoiceInput = () => {
|
|
5
6
|
const [isConnected, setIsConnected] = useState(false);
|
package/src/index.ts
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
import { Platform } from 'react-native';
|
|
2
2
|
import { NitroModules } from 'react-native-nitro-modules';
|
|
3
3
|
import AutoPlayHeadlessJsTask from './AutoPlayHeadlessJsTask';
|
|
4
|
+
import { HybridAndroidAutoTelemetry } from './hybrid/HybridAndroidAutoTelemetry';
|
|
5
|
+
import { HybridAutoPlay } from './hybrid/HybridAutoPlay';
|
|
4
6
|
import type { AndroidAutomotive } from './specs/AndroidAutomotive.nitro';
|
|
5
|
-
import type { AndroidAutoTelemetry as NitroAndroidAutoTelemetry } from './specs/AndroidAutoTelemetry.nitro';
|
|
6
|
-
import type { AutoPlay as NitroAutoPlay } from './specs/AutoPlay.nitro';
|
|
7
7
|
|
|
8
|
-
AutoPlayHeadlessJsTask.registerHeadlessTask();
|
|
8
|
+
AutoPlayHeadlessJsTask.registerHeadlessTask(HybridAutoPlay);
|
|
9
9
|
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
export const HybridAndroidAutoTelemetry =
|
|
13
|
-
Platform.OS === 'android'
|
|
14
|
-
? NitroModules.createHybridObject<NitroAndroidAutoTelemetry>('AndroidAutoTelemetry')
|
|
15
|
-
: null;
|
|
10
|
+
export { HybridAutoPlay };
|
|
11
|
+
export { HybridAndroidAutoTelemetry };
|
|
16
12
|
|
|
17
13
|
export const HybridAndroidAutomotive =
|
|
18
14
|
Platform.OS === 'android'
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { AppRegistry, Platform } from 'react-native';
|
|
3
3
|
import { NitroModules } from 'react-native-nitro-modules';
|
|
4
|
-
import { HybridAutoPlay } from '..';
|
|
5
4
|
import { SafeAreaInsetsProvider } from '../components/SafeAreaInsetsContext';
|
|
5
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
6
6
|
import type {
|
|
7
7
|
BaseCarPlayDashboardButton,
|
|
8
8
|
CarPlayDashboard as NitroCarPlayDashboard,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { AppRegistry, Platform } from 'react-native';
|
|
3
3
|
import { NitroModules } from 'react-native-nitro-modules';
|
|
4
|
-
import {
|
|
4
|
+
import type { AutoText } from '..';
|
|
5
5
|
import { MapTemplateProvider } from '../components/MapTemplateContext';
|
|
6
6
|
import { SafeAreaInsetsProvider } from '../components/SafeAreaInsetsContext';
|
|
7
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
7
8
|
import type { MapTemplate as NitroMapTemplate } from '../specs/MapTemplate.nitro';
|
|
8
9
|
import type { ActionButtonAndroid, MapButton, MapPanButton } from '../types/Button';
|
|
9
10
|
import type { AutoManeuver } from '../types/Maneuver';
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Platform } from 'react-native';
|
|
2
2
|
import { NitroModules } from 'react-native-nitro-modules';
|
|
3
3
|
import uuid from 'react-native-uuid';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
type TextButton,
|
|
4
|
+
import type {
|
|
5
|
+
AutoImage,
|
|
6
|
+
BaseMapTemplateConfig,
|
|
7
|
+
CustomActionButtonAndroid,
|
|
8
|
+
HeaderActionsAndroid,
|
|
9
|
+
TextButton,
|
|
11
10
|
} from '..';
|
|
11
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
12
12
|
import type { MessageTemplate as NitroMessageTemplate } from '../specs/MessageTemplate.nitro';
|
|
13
13
|
import type { AutoText } from '../types/Text';
|
|
14
14
|
import { type NitroAction, NitroActionUtil } from '../utils/NitroAction';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import uuid from 'react-native-uuid';
|
|
2
|
-
import { HybridAutoPlay } from '
|
|
2
|
+
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
3
3
|
import type { ActionButtonAndroid, ActionButtonIos, AppButton, BackButton } from '../types/Button';
|
|
4
4
|
import { type NitroAction, NitroActionUtil } from '../utils/NitroAction';
|
|
5
5
|
import type { NitroMapButton } from '../utils/NitroMapButton';
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
package com.margelo.nitro.swe.iternio.reactnativeautoplay.utils
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.ReactApplication
|
|
4
|
-
import com.facebook.react.ReactInstanceEventListener
|
|
5
|
-
import com.facebook.react.bridge.ReactContext
|
|
6
|
-
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
7
|
-
import kotlin.coroutines.resume
|
|
8
|
-
|
|
9
|
-
object ReactContextResolver {
|
|
10
|
-
suspend fun getReactContext(application: ReactApplication): ReactContext {
|
|
11
|
-
val host =
|
|
12
|
-
application.reactHost ?: throw IllegalArgumentException("application host null")
|
|
13
|
-
|
|
14
|
-
return suspendCancellableCoroutine { continuation ->
|
|
15
|
-
host.currentReactContext?.let {
|
|
16
|
-
continuation.resume(it)
|
|
17
|
-
return@suspendCancellableCoroutine
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
val listener = object : ReactInstanceEventListener {
|
|
21
|
-
override fun onReactContextInitialized(context: ReactContext) {
|
|
22
|
-
host.removeReactInstanceEventListener(this)
|
|
23
|
-
continuation.resume(context)
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
host.addReactInstanceEventListener(listener)
|
|
27
|
-
|
|
28
|
-
continuation.invokeOnCancellation {
|
|
29
|
-
host.removeReactInstanceEventListener(listener)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
host.start()
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
}
|