@mentra/crust 0.1.0-beta.0
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/README.md +41 -0
- package/android/build.gradle +146 -0
- package/android/src/internal/AndroidManifest.xml +9 -0
- package/android/src/internal/java/com/mentra/crust/receivers/CaptionsTesterIncidentReceiver.kt +46 -0
- package/android/src/main/AndroidManifest.xml +19 -0
- package/android/src/main/java/com/mentra/crust/CrustModule.kt +1042 -0
- package/android/src/main/java/com/mentra/crust/CrustView.kt +30 -0
- package/android/src/main/java/com/mentra/crust/heading/HeadingManager.kt +150 -0
- package/android/src/main/java/com/mentra/crust/jsc/JSCDispatcher.kt +189 -0
- package/android/src/main/java/com/mentra/crust/jsc/JSCPolyfillBridge.kt +287 -0
- package/android/src/main/java/com/mentra/crust/jsc/JSCRuntime.kt +593 -0
- package/android/src/main/java/com/mentra/crust/navigation/NavigationManager.kt +1445 -0
- package/android/src/main/java/com/mentra/crust/services/NotificationListener.kt +319 -0
- package/android/src/main/java/com/mentra/crust/utils/ImageProcessor.java +452 -0
- package/android/src/main/java/com/mentra/crust/utils/VideoStabilizer.kt +556 -0
- package/android/src/main/res/values/strings.xml +3 -0
- package/app.plugin.js +3 -0
- package/build/Crust.types.d.ts +148 -0
- package/build/Crust.types.d.ts.map +1 -0
- package/build/Crust.types.js +2 -0
- package/build/Crust.types.js.map +1 -0
- package/build/CrustModule.d.ts +182 -0
- package/build/CrustModule.d.ts.map +1 -0
- package/build/CrustModule.js +4 -0
- package/build/CrustModule.js.map +1 -0
- package/build/CrustModule.web.d.ts +34 -0
- package/build/CrustModule.web.d.ts.map +1 -0
- package/build/CrustModule.web.js +63 -0
- package/build/CrustModule.web.js.map +1 -0
- package/build/CrustView.d.ts +4 -0
- package/build/CrustView.d.ts.map +1 -0
- package/build/CrustView.js +7 -0
- package/build/CrustView.js.map +1 -0
- package/build/CrustView.web.d.ts +4 -0
- package/build/CrustView.web.d.ts.map +1 -0
- package/build/CrustView.web.js +7 -0
- package/build/CrustView.web.js.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +6 -0
- package/build/index.js.map +1 -0
- package/expo-module.config.json +9 -0
- package/ios/Crust.podspec +65 -0
- package/ios/CrustModule.swift +781 -0
- package/ios/CrustView.swift +38 -0
- package/ios/Resources/startup.js +814 -0
- package/ios/Source/JSCDispatcher.swift +226 -0
- package/ios/Source/JSCPolyfillBridge.swift +378 -0
- package/ios/Source/JSCRuntime.swift +673 -0
- package/ios/Source/utils/ImageProcessor.swift +392 -0
- package/ios/Source/utils/SystemGestures.swift +53 -0
- package/ios/Source/utils/VideoStabilizer.swift +374 -0
- package/ios/heading/HeadingManager.swift +74 -0
- package/ios/navigation/NavPayloads.swift +62 -0
- package/ios/navigation/NavigationManager.swift +720 -0
- package/package.json +69 -0
- package/plugin/build/index.d.ts +19 -0
- package/plugin/build/index.js +23 -0
- package/plugin/build/withAndroid.d.ts +2 -0
- package/plugin/build/withAndroid.js +78 -0
- package/src/Crust.types.ts +157 -0
- package/src/CrustModule.ts +191 -0
- package/src/CrustModule.web.ts +66 -0
- package/src/CrustView.tsx +10 -0
- package/src/CrustView.web.tsx +11 -0
- package/src/index.ts +5 -0
package/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# @mentra/crust
|
|
2
|
+
|
|
3
|
+
The MentraOS native runtime layer: an [Expo module](https://docs.expo.dev/modules/overview/)
|
|
4
|
+
providing the native capabilities the Mentra Engine's miniapp runtime sits on —
|
|
5
|
+
per-miniapp JS contexts (QuickJS on Android, JavaScriptCore on iOS), the
|
|
6
|
+
native side of the MentraJS bridge, navigation, and device utilities.
|
|
7
|
+
|
|
8
|
+
You don't call crust directly from app code: it's a **peer dependency of
|
|
9
|
+
[`@mentra/engine`](https://www.npmjs.com/package/@mentra/engine)**. A host app
|
|
10
|
+
embedding the engine installs crust alongside it and Expo autolinking picks it
|
|
11
|
+
up.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install @mentra/crust@dev
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
> Currently published on the `dev` dist-tag (prerelease channel).
|
|
20
|
+
|
|
21
|
+
## Config plugin
|
|
22
|
+
|
|
23
|
+
The package ships an Expo config plugin (`app.plugin.js`) that carries its
|
|
24
|
+
Android build contract — Mapbox's maven repository, protobuf exclusions, and
|
|
25
|
+
core-library desugaring. Add it to the host app's Expo config:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{"expo": {"plugins": ["@mentra/crust"]}}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Building with the navigation feature requires a `MAPBOX_DOWNLOADS_TOKEN` in
|
|
32
|
+
the Android build environment (Mapbox's SDK repository is authenticated).
|
|
33
|
+
|
|
34
|
+
At build time the Android side also reads the MentraJS polyfill bundle from
|
|
35
|
+
its [`@mentra/jspolyfill`](https://www.npmjs.com/package/@mentra/jspolyfill)
|
|
36
|
+
sibling, which is declared as a dependency.
|
|
37
|
+
|
|
38
|
+
## Part of MentraOS
|
|
39
|
+
|
|
40
|
+
Source lives in the [MentraOS monorepo](https://github.com/Mentra-Community/MentraOS)
|
|
41
|
+
under `mobile/modules/crust`. Issues and contributions welcome there.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
apply plugin: 'com.android.library'
|
|
2
|
+
|
|
3
|
+
group = 'com.mentra.crust'
|
|
4
|
+
version = '0.1.0'
|
|
5
|
+
|
|
6
|
+
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
7
|
+
apply from: expoModulesCorePlugin
|
|
8
|
+
applyKotlinExpoModulesCorePlugin()
|
|
9
|
+
useCoreDependencies()
|
|
10
|
+
useExpoPublishing()
|
|
11
|
+
|
|
12
|
+
// MentraJS Android runtime: QuickJS via dokar3/quickjs-kt.
|
|
13
|
+
//
|
|
14
|
+
// Zipline's `bind(name, service)` registers services in an internal Kotlin
|
|
15
|
+
// map keyed by name for the Kotlin/JS-compiled `Zipline.take()` API; it does
|
|
16
|
+
// not install JS globals on globalThis. Our polyfill is hand-written JS that
|
|
17
|
+
// reads `globalThis.__mentraNativeBridge`, so the Zipline path silently
|
|
18
|
+
// dropped every JS→host dispatch on Android.
|
|
19
|
+
//
|
|
20
|
+
// dokar3/quickjs-kt exposes `QuickJs.function(name) { args -> ... }` which
|
|
21
|
+
// installs the lambda directly as a property of globalThis via QuickJS's
|
|
22
|
+
// `JS_SetPropertyStr(JS_NewCFunction(...))`. This matches iOS Apple JSC's
|
|
23
|
+
// `ctx.setObject(closure, forKeyedSubscript: ...)` pattern point-for-point.
|
|
24
|
+
|
|
25
|
+
// If you want to use the managed Android SDK versions from expo-modules-core, set this to true.
|
|
26
|
+
// The Android SDK versions will be bumped from time to time in SDK releases and may introduce breaking changes in your module code.
|
|
27
|
+
// Most of the time, you may like to manage the Android SDK versions yourself.
|
|
28
|
+
def useManagedAndroidSdkVersions = false
|
|
29
|
+
if (useManagedAndroidSdkVersions) {
|
|
30
|
+
useDefaultAndroidSdkVersions()
|
|
31
|
+
} else {
|
|
32
|
+
buildscript {
|
|
33
|
+
// Simple helper that allows the root project to override versions declared by this library.
|
|
34
|
+
ext.safeExtGet = { prop, fallback ->
|
|
35
|
+
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
project.android {
|
|
39
|
+
compileSdkVersion safeExtGet("compileSdkVersion", 36)
|
|
40
|
+
defaultConfig {
|
|
41
|
+
minSdkVersion safeExtGet("minSdkVersion", 24)
|
|
42
|
+
targetSdkVersion safeExtGet("targetSdkVersion", 36)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
android {
|
|
48
|
+
namespace "com.mentra.crust"
|
|
49
|
+
defaultConfig {
|
|
50
|
+
versionCode 1
|
|
51
|
+
versionName "0.1.0"
|
|
52
|
+
multiDexEnabled true
|
|
53
|
+
}
|
|
54
|
+
// Pull the MentraJS polyfill bundle from the sibling @mentra/jspolyfill
|
|
55
|
+
// module's `assets/` directory — single committed source of truth. The
|
|
56
|
+
// file is read at runtime via `appContext.assets.open("startup.js")`.
|
|
57
|
+
// Cross-module sourceSet entry beats checking the same artifact into git
|
|
58
|
+
// multiple times.
|
|
59
|
+
sourceSets {
|
|
60
|
+
main {
|
|
61
|
+
assets.srcDirs += '../../jspolyfill/assets'
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
compileOptions {
|
|
65
|
+
coreLibraryDesugaringEnabled true
|
|
66
|
+
}
|
|
67
|
+
buildTypes {
|
|
68
|
+
internal {
|
|
69
|
+
initWith release
|
|
70
|
+
matchingFallbacks = ['release']
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
buildTypes {
|
|
74
|
+
internal {
|
|
75
|
+
initWith release
|
|
76
|
+
matchingFallbacks = ['release']
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
lintOptions {
|
|
80
|
+
abortOnError false
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
dependencies {
|
|
85
|
+
// Mapbox Navigation SDK v3 (replaces Google Navigation SDK).
|
|
86
|
+
// Drives headless turn-by-turn nav in NavigationManager.kt: route
|
|
87
|
+
// progress, off-route + automatic rerouting, enhanced (map-matched)
|
|
88
|
+
// location, and the MapboxReplayer simulation harness for dev trips.
|
|
89
|
+
// Resolved from the authenticated Mapbox Downloads Maven repo, which is
|
|
90
|
+
// injected into the root project's allprojects.repositories at prebuild by
|
|
91
|
+
// mobile/plugins/android.ts (withProjectBuildGradleModifications), using the
|
|
92
|
+
// MAPBOX_DOWNLOADS_TOKEN (Downloads:Read sk.… token) from the env/gradle.properties.
|
|
93
|
+
//
|
|
94
|
+
// We depend on the headless modules directly, NOT the umbrella
|
|
95
|
+
// `navigationcore:android` artifact — that one also drags in `ui-maps`,
|
|
96
|
+
// `voice`, and `copilot`, which a custom glasses HUD doesn't use (dead
|
|
97
|
+
// APK weight). `:navigation` is the core engine; `:tripdata` carries the
|
|
98
|
+
// banner/maneuver formatting used to label turns.
|
|
99
|
+
// Version pinned to 3.25.0 — re-check https://docs.mapbox.com/android/navigation/releases/
|
|
100
|
+
def isChinaBuild = System.getenv("EXPO_PUBLIC_DEPLOYMENT_REGION") == "china"
|
|
101
|
+
if (isChinaBuild) {
|
|
102
|
+
compileOnly 'com.mapbox.navigationcore:navigation:3.25.0'
|
|
103
|
+
compileOnly 'com.mapbox.navigationcore:tripdata:3.25.0'
|
|
104
|
+
} else {
|
|
105
|
+
implementation 'com.mapbox.navigationcore:navigation:3.25.0'
|
|
106
|
+
implementation 'com.mapbox.navigationcore:tripdata:3.25.0'
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Required for Java 8+ APIs on minSdk < 26 (was needed by Google Nav SDK;
|
|
110
|
+
// Mapbox Nav SDK likewise targets desugared core libs).
|
|
111
|
+
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.4'
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
dependencies {
|
|
115
|
+
implementation 'com.google.android.gms:play-services-location:21.0.1'
|
|
116
|
+
implementation 'com.google.android.gms:play-services-base:18.2.0'
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
dependencies {
|
|
120
|
+
// MentraJS — QuickJS for per-miniapp JS contexts. dokar3/quickjs-kt is a
|
|
121
|
+
// KMP wrapper around Bellard QuickJS that exposes `function(name) { ... }`
|
|
122
|
+
// for installing Kotlin lambdas as JS globals via `JS_SetPropertyStr`.
|
|
123
|
+
// Mirrors iOS Apple JSC's `setObject(_, forKeyedSubscript:)` pattern.
|
|
124
|
+
//
|
|
125
|
+
// Version pin: this Expo SDK 55 build uses Kotlin 2.1.20, which can read
|
|
126
|
+
// metadata up to 2.2.0. dokar3 1.0.1+ ships classes with metadata 2.3.0
|
|
127
|
+
// (compiled with Kotlin 2.3.x) and is unreadable here. 1.0.0-alpha13 is
|
|
128
|
+
// the last release compiled with Kotlin 2.0 (metadata 2.0.0) — its API
|
|
129
|
+
// (`QuickJs.create`, `evaluate`, `function` extension) matches 1.0.5 1:1.
|
|
130
|
+
// Bump only when the host Kotlin compiler clears 2.3.0 metadata.
|
|
131
|
+
implementation 'io.github.dokar3:quickjs-kt-android:1.0.0-alpha13'
|
|
132
|
+
|
|
133
|
+
// OkHttp for fetch / WebSocket — already used elsewhere in MentraOS;
|
|
134
|
+
// pinned here so the gradle plugin doesn't downgrade us.
|
|
135
|
+
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
|
|
136
|
+
|
|
137
|
+
// Tink for X25519 (Android stdlib X25519 is API 33+ only; minSdk is 24).
|
|
138
|
+
// ~1.2 MB AAR. Crypto.subtle's SHA / AES-GCM / HMAC stay on javax.crypto
|
|
139
|
+
// which ships on the platform.
|
|
140
|
+
implementation 'com.google.crypto.tink:tink-android:1.14.1'
|
|
141
|
+
|
|
142
|
+
// Kotlin coroutines: dokar3's `evaluate()` is suspend; we bridge it via
|
|
143
|
+
// `runBlocking(dispatcher)` from the per-miniapp single-thread executor.
|
|
144
|
+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1'
|
|
145
|
+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1'
|
|
146
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
2
|
+
<application>
|
|
3
|
+
<receiver android:name="com.mentra.crust.receivers.CaptionsTesterIncidentReceiver" android:exported="true">
|
|
4
|
+
<intent-filter>
|
|
5
|
+
<action android:name="com.mentra.CAPTIONS_TESTER_INCIDENT"/>
|
|
6
|
+
</intent-filter>
|
|
7
|
+
</receiver>
|
|
8
|
+
</application>
|
|
9
|
+
</manifest>
|
package/android/src/internal/java/com/mentra/crust/receivers/CaptionsTesterIncidentReceiver.kt
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
package com.mentra.crust.receivers
|
|
2
|
+
|
|
3
|
+
import android.content.BroadcastReceiver
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.content.Intent
|
|
6
|
+
import android.util.Log
|
|
7
|
+
import com.mentra.crust.CrustModule
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Receives broadcasts from the external captions tester and forwards them into React Native so
|
|
11
|
+
* the app can file a normal incident through the existing mobile incident pipeline.
|
|
12
|
+
*/
|
|
13
|
+
class CaptionsTesterIncidentReceiver : BroadcastReceiver() {
|
|
14
|
+
@Suppress("DEPRECATION")
|
|
15
|
+
override fun onReceive(context: Context?, intent: Intent?) {
|
|
16
|
+
if (intent == null) {
|
|
17
|
+
Log.w("CaptionsTesterIncident", "Received null intent")
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
val body =
|
|
22
|
+
hashMapOf<String, Any>(
|
|
23
|
+
"action" to (intent.action ?: "unknown"),
|
|
24
|
+
"timestamp" to System.currentTimeMillis(),
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
intent.getStringExtra("failure_code")?.let { body["failure_code"] = it }
|
|
28
|
+
intent.getStringExtra("failure_message")?.let { body["failure_message"] = it }
|
|
29
|
+
intent.getStringExtra("test_run_id")?.let { body["test_run_id"] = it }
|
|
30
|
+
intent.getStringExtra("scenario_name")?.let { body["scenario_name"] = it }
|
|
31
|
+
intent.getStringExtra("source")?.let { body["source"] = it }
|
|
32
|
+
|
|
33
|
+
intent.extras?.keySet()?.forEach { key ->
|
|
34
|
+
if (body.containsKey(key)) {
|
|
35
|
+
return@forEach
|
|
36
|
+
}
|
|
37
|
+
val value = intent.extras?.get(key) ?: return@forEach
|
|
38
|
+
when (value) {
|
|
39
|
+
is String, is Int, is Long, is Boolean, is Double, is Float -> body[key] = value
|
|
40
|
+
else -> body[key] = value.toString()
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
CrustModule.emitCaptionsTesterIncident(body)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
2
|
+
<application>
|
|
3
|
+
<service
|
|
4
|
+
android:name="com.mentra.crust.services.NotificationListenerServiceImpl"
|
|
5
|
+
android:label="@string/mentra_crust_notification_listener_label"
|
|
6
|
+
android:exported="false"
|
|
7
|
+
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
|
|
8
|
+
<intent-filter>
|
|
9
|
+
<action android:name="android.service.notification.NotificationListenerService" />
|
|
10
|
+
</intent-filter>
|
|
11
|
+
<meta-data android:name="android.service.notification.default_filter_types" android:value="conversations|alerting" />
|
|
12
|
+
<meta-data android:name="android.service.notification.disabled_filter_types" android:value="ongoing|silent" />
|
|
13
|
+
</service>
|
|
14
|
+
|
|
15
|
+
<!-- The Mapbox Navigation SDK delivers turn-by-turn steps inline via
|
|
16
|
+
RouteProgress (no Messenger-IPC service), so the Google-era
|
|
17
|
+
NavInfoReceiverService is gone. Nothing to register here for nav. -->
|
|
18
|
+
</application>
|
|
19
|
+
</manifest>
|