@glassly/engine 0.3.8-dev.999 → 0.4.0-beta.1023

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 (86) hide show
  1. package/build/engine.d.ts +11 -0
  2. package/build/engine.d.ts.map +1 -1
  3. package/build/facades/ai.d.ts +6 -0
  4. package/build/facades/ai.d.ts.map +1 -1
  5. package/build/facades/ai.js +6 -0
  6. package/build/facades/ai.js.map +1 -1
  7. package/build/facades/glasses.d.ts +9 -1
  8. package/build/facades/glasses.d.ts.map +1 -1
  9. package/build/facades/glasses.js +13 -0
  10. package/build/facades/glasses.js.map +1 -1
  11. package/build/generated/releaseMetadata.js +4 -4
  12. package/build/generated/releaseMetadata.js.map +1 -1
  13. package/build/index.d.ts +1 -1
  14. package/build/index.d.ts.map +1 -1
  15. package/build/index.js.map +1 -1
  16. package/build/services/CloudClientService.d.ts +2 -1
  17. package/build/services/CloudClientService.d.ts.map +1 -1
  18. package/build/services/CloudClientService.js +8 -0
  19. package/build/services/CloudClientService.js.map +1 -1
  20. package/build/services/DeviceEventRouter.d.ts.map +1 -1
  21. package/build/services/DeviceEventRouter.js +1 -0
  22. package/build/services/DeviceEventRouter.js.map +1 -1
  23. package/build/services/GlassesSensorService.js +1 -1
  24. package/build/services/GlassesSensorService.js.map +1 -1
  25. package/build/services/LlmRouting.d.ts +1 -1
  26. package/build/services/LlmRouting.js.map +1 -1
  27. package/build/services/LocalLlmModelManager.d.ts +22 -2
  28. package/build/services/LocalLlmModelManager.d.ts.map +1 -1
  29. package/build/services/LocalLlmModelManager.js +104 -2
  30. package/build/services/LocalLlmModelManager.js.map +1 -1
  31. package/build/services/LocalLlmProvider.d.ts.map +1 -1
  32. package/build/services/LocalLlmProvider.js +11 -0
  33. package/build/services/LocalLlmProvider.js.map +1 -1
  34. package/build/services/LocalMiniappRuntime.d.ts +13 -0
  35. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  36. package/build/services/LocalMiniappRuntime.js +61 -5
  37. package/build/services/LocalMiniappRuntime.js.map +1 -1
  38. package/build/services/NavigationHandlers.js +1 -1
  39. package/build/services/NavigationHandlers.js.map +1 -1
  40. package/build/services/NavigationService.js +6 -6
  41. package/build/services/NavigationService.js.map +1 -1
  42. package/build/services/controllers.d.ts.map +1 -1
  43. package/build/services/controllers.js +1 -0
  44. package/build/services/controllers.js.map +1 -1
  45. package/build/services/neuralBand/HandwritingGate.d.ts +38 -0
  46. package/build/services/neuralBand/HandwritingGate.d.ts.map +1 -0
  47. package/build/services/neuralBand/HandwritingGate.js +89 -0
  48. package/build/services/neuralBand/HandwritingGate.js.map +1 -0
  49. package/build/services/neuralBand/NeuralBandInput.d.ts +12 -1
  50. package/build/services/neuralBand/NeuralBandInput.d.ts.map +1 -1
  51. package/build/services/neuralBand/NeuralBandInput.js +27 -0
  52. package/build/services/neuralBand/NeuralBandInput.js.map +1 -1
  53. package/build/services/neuralBand/NeuralBandSettingsSync.d.ts.map +1 -1
  54. package/build/services/neuralBand/NeuralBandSettingsSync.js +36 -3
  55. package/build/services/neuralBand/NeuralBandSettingsSync.js.map +1 -1
  56. package/build/stores/appVisibility.d.ts.map +1 -1
  57. package/build/stores/appVisibility.js +0 -1
  58. package/build/stores/appVisibility.js.map +1 -1
  59. package/build/stores/settings.d.ts.map +1 -1
  60. package/build/stores/settings.js +26 -0
  61. package/build/stores/settings.js.map +1 -1
  62. package/build/types/enums.d.ts +2 -1
  63. package/build/types/enums.d.ts.map +1 -1
  64. package/build/types/enums.js +1 -0
  65. package/build/types/enums.js.map +1 -1
  66. package/package.json +7 -7
  67. package/src/facades/ai.ts +6 -0
  68. package/src/facades/glasses.ts +17 -0
  69. package/src/generated/releaseMetadata.ts +4 -4
  70. package/src/index.ts +1 -0
  71. package/src/services/CloudClientService.ts +8 -0
  72. package/src/services/DeviceEventRouter.ts +1 -0
  73. package/src/services/GlassesSensorService.ts +1 -1
  74. package/src/services/LlmRouting.ts +1 -1
  75. package/src/services/LocalLlmModelManager.ts +110 -3
  76. package/src/services/LocalLlmProvider.ts +8 -0
  77. package/src/services/LocalMiniappRuntime.ts +66 -5
  78. package/src/services/NavigationHandlers.ts +1 -1
  79. package/src/services/NavigationService.ts +6 -6
  80. package/src/services/controllers.ts +1 -0
  81. package/src/services/neuralBand/HandwritingGate.ts +111 -0
  82. package/src/services/neuralBand/NeuralBandInput.ts +37 -1
  83. package/src/services/neuralBand/NeuralBandSettingsSync.ts +46 -3
  84. package/src/stores/appVisibility.ts +0 -1
  85. package/src/stores/settings.ts +26 -0
  86. package/src/types/enums.ts +1 -0
@@ -124,7 +124,7 @@ export class NavigationHandlers {
124
124
  const simulate = payload.simulate === true;
125
125
  const speedNum = Number(payload.speedMultiplier);
126
126
  const speedMultiplier = Number.isFinite(speedNum) && speedNum > 0 ? speedNum : 5;
127
- const mode = typeof payload.mode === "string" ? payload.mode : "driving";
127
+ const mode = typeof payload.mode === "string" ? payload.mode : "walking";
128
128
  const avoidRaw = payload.avoid;
129
129
  const avoid = avoidRaw
130
130
  ? {
@@ -1 +1 @@
1
- {"version":3,"file":"NavigationHandlers.js","sourceRoot":"","sources":["../../src/services/NavigationHandlers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * NavigationHandlers — turn-by-turn navigation request handlers for\n * LocalMiniappRuntime. Extracted from LocalMiniappRuntime so the\n * navigation surface (Google Maps Navigation SDK adapter, multi-stop\n * routes, deviation simulator, dev toggles, road-snapped GPS streaming)\n * lives in one file the reviewer can read in isolation.\n *\n * Wire-up: LocalMiniappRuntime owns one instance, constructed with\n * callbacks for sending results / events back to the miniapp. The\n * dispatcher's switch statement delegates each `NAVIGATION_*` case to a\n * handler here. Cross-cutting hooks (cleanup on disconnect, location-\n * stream gating during a trip) are exposed via {@link onDisconnect} and\n * {@link isTripActive}.\n *\n * State owned here:\n * - navListeners: per-package unsubscribers for the nav-update +\n * road-snapped-location + route streams. Detached on disconnect,\n * reattached on the next NAVIGATION_START from the same package.\n * - activeNavApps: packages with a live nav session. Used by the\n * dispatcher to gate raw background-GPS forwards (we don't want the\n * unsnapped fix interleaving with the simulator's snapped output\n * during a trip).\n */\n\nimport {type NavLocation, type NavRoute, type NavUpdate} from \"../runtime/config\"\nimport {cloudClientService} from \"./CloudClientService\"\nimport nativeNavigationService from \"./NativeNavigationService\"\nimport navigationService from \"./NavigationService\"\nimport {MiniappErrorCode, MiniappResponseType, MiniappStreamType} from \"@glassly/miniapp\"\n\nconst LOG_TAG = \"LocalMiniappRuntime\"\n\n/**\n * Shape of the per-miniapp envelope sender — matches\n * LocalMiniappRuntime.sendToMiniapp's signature.\n */\ntype SendToMiniapp = (\n packageName: string,\n envelope: {type: MiniappResponseType; streamType?: MiniappStreamType; data?: unknown},\n) => void\n\n/**\n * Shape of the request-result sender — matches\n * LocalMiniappRuntime.sendResult's signature.\n */\ntype SendResult = (\n packageName: string,\n requestId: string | undefined,\n ok: boolean,\n result?: unknown,\n error?: {code: MiniappErrorCode; message: string},\n) => void\n\nexport class NavigationHandlers {\n /** packageName → unsubscribe fn for that app's nav event forwarder. */\n private navListeners = new Map<string, () => void>()\n /** Set of packageNames that have called navigation.start() and not yet stop(). */\n private activeNavApps = new Set<string>()\n\n constructor(\n private readonly sendToMiniapp: SendToMiniapp,\n private readonly sendResult: SendResult,\n ) {\n nativeNavigationService.setOnGlassesExit(() => this.stopFromGlasses())\n }\n\n /**\n * The wearer exited nav mode on the glasses — end the trip: stop the native\n * navigator and tell each active nav app via a \"cancelled\" update so it can\n * reset its own trip state.\n */\n private stopFromGlasses(): void {\n if (this.activeNavApps.size === 0) return\n console.log(`${LOG_TAG}: nav mode exited on glasses — stopping trip for ${[...this.activeNavApps].join(\", \")}`)\n for (const packageName of this.activeNavApps) {\n this.sendToMiniapp(packageName, {\n type: MiniappResponseType.EVENT,\n streamType: MiniappStreamType.NAVIGATION_UPDATE,\n data: {kind: \"cancelled\", reason: \"glasses\"},\n })\n }\n this.activeNavApps.clear()\n void navigationService.stop().catch((err: unknown) => {\n console.error(`${LOG_TAG}: navigation stop after glasses exit failed:`, err)\n })\n }\n\n /** True iff a trip is currently active for the package (used to gate raw-GPS forwards). */\n isTripActive(packageName: string): boolean {\n return this.activeNavApps.has(packageName)\n }\n\n /**\n * Detach the per-app nav event forwarder. Called when the mini-app\n * disconnects. The native nav session is left running so the user can\n * reopen the app and reattach without losing their trip; `activeNavApps`\n * is kept intact for the same reason.\n */\n onDisconnect(packageName: string): void {\n const unsub = this.navListeners.get(packageName)\n if (unsub) {\n unsub()\n this.navListeners.delete(packageName)\n }\n }\n\n /**\n * The user closed/disabled the mini-app (not a crash-respawn). Unlike\n * {@link onDisconnect}, this ends the trip: the glasses leave native nav\n * mode and the phone navigator stops once no other app is navigating.\n */\n onAppClosed(packageName: string): void {\n this.onDisconnect(packageName)\n if (!this.activeNavApps.delete(packageName)) return\n if (this.activeNavApps.size > 0) return\n console.log(`${LOG_TAG}: ${packageName} closed with an active trip — stopping navigation`)\n nativeNavigationService.onTripEnd(false)\n void navigationService.stop().catch((err: unknown) => {\n console.error(`${LOG_TAG}: navigation stop after app close failed:`, err)\n })\n }\n\n async handleStart(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n console.log(`${LOG_TAG}: handleNavigationStart from ${packageName}`, JSON.stringify(payload))\n\n // v2 wire shape sends `stops`; v1 shape sends bare lat/lng. Accept both.\n const rawStops = payload.stops as Array<{lat?: unknown; lng?: unknown}> | undefined\n const stops: Array<{lat: number; lng: number}> = []\n if (Array.isArray(rawStops)) {\n for (const s of rawStops) {\n const sLat = Number(s?.lat)\n const sLng = Number(s?.lng)\n if (Number.isFinite(sLat) && Number.isFinite(sLng)) stops.push({lat: sLat, lng: sLng})\n }\n }\n if (stops.length === 0) {\n const lat = Number(payload.lat)\n const lng = Number(payload.lng)\n if (Number.isFinite(lat) && Number.isFinite(lng)) stops.push({lat, lng})\n }\n if (stops.length === 0) {\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: \"stops or lat/lng required\",\n })\n return\n }\n const lat = stops[0].lat\n const lng = stops[0].lng\n const simulate = payload.simulate === true\n const speedNum = Number(payload.speedMultiplier)\n const speedMultiplier = Number.isFinite(speedNum) && speedNum > 0 ? speedNum : 5\n const mode = typeof payload.mode === \"string\" ? payload.mode : \"driving\"\n const avoidRaw = payload.avoid as Record<string, unknown> | undefined\n const avoid = avoidRaw\n ? {\n highways: avoidRaw.highways === true,\n tolls: avoidRaw.tolls === true,\n ferries: avoidRaw.ferries === true,\n }\n : undefined\n const missedRaw = Number(payload.missedTurnRerouteMeters)\n const missedTurnRerouteMeters = Number.isFinite(missedRaw) && missedRaw > 0 ? missedRaw : undefined\n\n const navigation = navigationService\n if (!navigation) {\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: \"navigation adapter not configured on host\",\n })\n return\n }\n\n // Reattach the per-app event forwarder (it may have been detached when the\n // mini-app closed its UI without stopping the trip).\n if (!this.navListeners.has(packageName)) {\n const unsubNav = navigation.addListener((update: NavUpdate) => {\n this.sendToMiniapp(packageName, {\n type: MiniappResponseType.EVENT,\n streamType: MiniappStreamType.NAVIGATION_UPDATE,\n data: update,\n })\n // Trip ended naturally — keep the forwarder alive (miniapp may\n // restart nav) but remove from active set so stop() accounting\n // stays accurate.\n if (update.kind === \"arrived\" || update.kind === \"error\") {\n this.activeNavApps.delete(packageName)\n if (this.activeNavApps.size === 0) {\n nativeNavigationService.onTripEnd(update.kind === \"arrived\")\n }\n }\n })\n // Forward the nav-SDK's road-snapped GPS fixes as a location_update\n // stream, so the miniapp's existing session.events.onLocation(...) just\n // works while a trip is active.\n const unsubLoc = navigation.addLocationListener((loc: NavLocation) => {\n this.sendToMiniapp(packageName, {\n type: MiniappResponseType.EVENT,\n streamType: MiniappStreamType.LOCATION_UPDATE,\n data: {\n lat: loc.lat,\n lng: loc.lng,\n accuracy: loc.accuracy ?? undefined,\n timestamp: loc.timestamp,\n },\n })\n })\n const unsubRoute = navigation.addRouteListener((route: NavRoute) => {\n this.sendToMiniapp(packageName, {\n type: MiniappResponseType.EVENT,\n streamType: MiniappStreamType.NAVIGATION_ROUTE,\n data: route,\n })\n })\n this.navListeners.set(packageName, () => {\n unsubNav()\n unsubLoc()\n unsubRoute()\n })\n }\n\n // If a trip is already active for this app (user closed the UI and came\n // back), reuse the running session — replay current snapshot and return\n // ok without restarting the native navigator.\n if (this.activeNavApps.has(packageName) && navigation.getState() !== \"idle\") {\n console.log(`${LOG_TAG}: resuming existing nav session for ${packageName}`)\n const snapshot = navigation.getSnapshot()\n this.sendResult(packageName, requestId, true, {ok: true, resumed: true, snapshot})\n return\n }\n\n try {\n const result = await navigation.start(\n {lat, lng},\n {simulate, speedMultiplier, stops, mode, avoid, missedTurnRerouteMeters},\n )\n if (result.ok) {\n this.activeNavApps.add(packageName)\n // Glasses with a firmware-rendered nav UI (G2) enter their native\n // navigation mode for the duration of the trip.\n nativeNavigationService.onTripStart(packageName)\n }\n // A refused start (`{ok: false, error}` from the token gate or the\n // native navigator) is request DATA, not a wire failure: the SDK's\n // navigation.start() contract is \"resolves {ok, error?}, never throws\".\n // Sending it as ok:false on the wire made the SDK reject with its\n // generic \"Unknown error\" and drop the real message.\n this.sendResult(packageName, requestId, true, result)\n } catch (err) {\n console.error(`${LOG_TAG}: navigation start error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation start error\",\n })\n }\n }\n\n async handleStop(packageName: string, requestId?: string): Promise<void> {\n try {\n const unsub = this.navListeners.get(packageName)\n if (unsub) {\n unsub()\n this.navListeners.delete(packageName)\n }\n this.activeNavApps.delete(packageName)\n // Only stop the native trip when no other miniapp is still navigating.\n if (this.activeNavApps.size === 0) {\n nativeNavigationService.onTripEnd(false)\n const navigation = navigationService\n const result = navigation ? await navigation.stop() : {ok: true}\n this.sendResult(packageName, requestId, true, result)\n } else {\n this.sendResult(packageName, requestId, true, {ok: true}, undefined)\n }\n } catch (err) {\n console.error(`${LOG_TAG}: navigation stop error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation stop error\",\n })\n }\n }\n\n async handleDeviate(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n try {\n const offsetNum = Number(payload.offsetMeters)\n const offsetMeters = Number.isFinite(offsetNum) && offsetNum > 0 ? offsetNum : 20\n const navigation = navigationService\n const result = navigation\n ? await navigation.simulateDeviation(offsetMeters)\n : {ok: false, error: \"navigation adapter not configured\"}\n this.sendResult(packageName, requestId, true, result)\n } catch (err) {\n console.error(`${LOG_TAG}: navigation deviate error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation deviate error\",\n })\n }\n }\n\n async handleSetWrongSidewalk(\n packageName: string,\n payload: Record<string, unknown>,\n requestId?: string,\n ): Promise<void> {\n try {\n const enabled = payload.enabled === true\n const navigation = navigationService\n const result = navigation\n ? await navigation.setWrongSidewalkOffset(enabled)\n : {ok: false, error: \"navigation adapter not configured\"}\n this.sendResult(packageName, requestId, true, result)\n } catch (err) {\n console.error(`${LOG_TAG}: navigation setWrongSidewalkOffset error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation setWrongSidewalkOffset error\",\n })\n }\n }\n\n async handleSetSkipCrossings(\n packageName: string,\n payload: Record<string, unknown>,\n requestId?: string,\n ): Promise<void> {\n try {\n const enabled = payload.enabled === true\n const navigation = navigationService\n const result = navigation\n ? await navigation.setSkipCrossings(enabled)\n : {ok: false, error: \"navigation adapter not configured\"}\n this.sendResult(packageName, requestId, true, result)\n } catch (err) {\n console.error(`${LOG_TAG}: navigation setSkipCrossings error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation setSkipCrossings error\",\n })\n }\n }\n\n handleGetState(packageName: string, requestId?: string): void {\n const snapshot = navigationService.getSnapshot() ?? null\n this.sendResult(packageName, requestId, true, {state: snapshot})\n }\n\n async handleRequestPermission(packageName: string, requestId?: string): Promise<void> {\n try {\n const navigation = navigationService\n const result = navigation\n ? await navigation.requestPermission()\n : {ok: false, accepted: false, error: \"navigation adapter not configured\"}\n this.sendResult(packageName, requestId, true, result)\n } catch (err) {\n console.error(`${LOG_TAG}: navigation requestPermission error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation requestPermission error\",\n })\n }\n }\n\n async handleComputeRoute(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n try {\n // With the user's own Mapbox key (Settings > API Keys), compute\n // on-device so routing works without the cloud and bills their account.\n // Without one, go through the v2 cloud maps proxy — org-token Mapbox\n // usage only ever happens cloud-side.\n if (navigationService.hasMapboxToken()) {\n const local = await navigationService.computeRoute(payload)\n if (local.ok) {\n this.sendResult(packageName, requestId, true, {ok: true, routes: local.routes ?? []})\n return\n }\n console.warn(`${LOG_TAG}: local computeRoute failed, falling back to cloud:`, local.error)\n }\n\n // Computed in the v2 cloud (provider-abstracted maps service). The SDK\n // payload shape ({origin, stops, mode, avoid, alternatives}) is the v2\n // DirectionsRequest field-for-field, so it passes straight through.\n const {routes} = await cloudClientService.maps.directions(payload as never)\n this.sendResult(packageName, requestId, true, {ok: true, routes})\n } catch (err) {\n console.error(`${LOG_TAG}: navigation computeRoute error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation computeRoute error\",\n })\n }\n }\n\n /**\n * Reverse-geocode a coordinate into a short road name + full formatted\n * address. Backs the SDK pivot engine's road-name fallback (`road`) and the\n * navigation miniapp's dropped-pin / POI-tap labels (`address`). Always\n * resolves with `{ok, road?, address?}` — a missing road/address is\n * `{ok: true, road: null, address: null}`, not an error.\n */\n async handleReverseGeocode(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n try {\n const lat = Number(payload.lat)\n const lng = Number(payload.lng)\n if (!Number.isFinite(lat) || !Number.isFinite(lng)) {\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: \"lat/lng required\",\n })\n return\n }\n // With the user's own Mapbox key, resolve on-device so this works\n // without the cloud; otherwise use the v2 cloud maps service.\n if (navigationService.hasMapboxToken()) {\n const local = await navigationService.reverseGeocodeRoad({lat, lng})\n if (local.ok) {\n this.sendResult(packageName, requestId, true, {\n ok: true,\n road: local.road ?? null,\n address: local.address ?? null,\n })\n return\n }\n console.warn(`${LOG_TAG}: local reverseGeocode failed, falling back to cloud:`, local.error)\n }\n\n const {road, address} = await cloudClientService.maps.reverseGeocode({lat, lng})\n this.sendResult(packageName, requestId, true, {ok: true, road, address})\n } catch (err) {\n console.error(`${LOG_TAG}: navigation reverseGeocode error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation reverseGeocode error\",\n })\n }\n }\n\n /**\n * Type-ahead place search. Runs on-device against Mapbox Search Box when the\n * user saved their own key (Settings > API Keys) — that key exists precisely\n * so search works without the cloud — and falls back to the v2 cloud maps\n * service otherwise. Resolves `{ok: true, suggestions}` — an empty query or no\n * matches is `{ok: true, suggestions: []}`, not an error.\n */\n async handlePlaceAutocomplete(\n packageName: string,\n payload: Record<string, unknown>,\n requestId?: string,\n ): Promise<void> {\n try {\n const query = typeof payload.query === \"string\" ? payload.query : \"\"\n const sessionToken = typeof payload.sessionToken === \"string\" ? payload.sessionToken : \"\"\n const near = this.parseNear(payload.near)\n\n if (navigationService.hasMapboxToken()) {\n const local = await navigationService.placeAutocomplete(query, near, sessionToken)\n if (local.ok) {\n this.sendResult(packageName, requestId, true, {ok: true, suggestions: local.suggestions ?? []})\n return\n }\n // A token is set but the direct call failed (bad key, offline, Mapbox\n // error). Fall through to the cloud rather than failing the search\n // outright.\n console.warn(`${LOG_TAG}: local placeAutocomplete failed, falling back to cloud:`, local.error)\n }\n\n const {suggestions} = await cloudClientService.maps.placeAutocomplete({query, near, sessionToken})\n this.sendResult(packageName, requestId, true, {ok: true, suggestions})\n } catch (err) {\n console.error(`${LOG_TAG}: navigation placeAutocomplete error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation placeAutocomplete error\",\n })\n }\n }\n\n /**\n * Resolve a suggestion (`placeId` + `sessionToken`) to a full place with\n * coordinates. Takes the same on-device-vs-cloud branch as\n * {@link handlePlaceAutocomplete}: the `placeId` and session token come from\n * whichever provider produced the suggestion, so both calls must run against\n * the same one. Resolves `{ok: true, place}`.\n */\n async handlePlaceDetails(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n try {\n const placeId = typeof payload.placeId === \"string\" ? payload.placeId : \"\"\n const sessionToken = typeof payload.sessionToken === \"string\" ? payload.sessionToken : \"\"\n if (!placeId) {\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: \"placeId required\",\n })\n return\n }\n\n if (navigationService.hasMapboxToken()) {\n const local = await navigationService.placeDetails(placeId, sessionToken)\n if (local.ok && local.place) {\n this.sendResult(packageName, requestId, true, {ok: true, place: local.place})\n return\n }\n // Don't fall back to the cloud here: this `placeId` came from a Mapbox\n // Search Box suggestion and is not resolvable by another provider.\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: local.error ?? \"navigation placeDetails error\",\n })\n return\n }\n\n const place = await cloudClientService.maps.placeDetails({placeId, sessionToken})\n this.sendResult(packageName, requestId, true, {ok: true, place})\n } catch (err) {\n console.error(`${LOG_TAG}: navigation placeDetails error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation placeDetails error\",\n })\n }\n }\n\n /** Coerce an inbound `near` payload to a {lat,lng}, or undefined when absent/invalid. */\n private parseNear(raw: unknown): {lat: number; lng: number} | undefined {\n if (!raw || typeof raw !== \"object\") return undefined\n const obj = raw as Record<string, unknown>\n const lat = Number(obj.lat)\n const lng = Number(obj.lng)\n if (!Number.isFinite(lat) || !Number.isFinite(lng)) return undefined\n return {lat, lng}\n }\n}\n"]}
1
+ {"version":3,"file":"NavigationHandlers.js","sourceRoot":"","sources":["../../src/services/NavigationHandlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAA;AACvD,OAAO,uBAAuB,MAAM,2BAA2B,CAAA;AAC/D,OAAO,iBAAiB,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAC,gBAAgB,EAAE,mBAAmB,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAA;AAEzF,MAAM,OAAO,GAAG,qBAAqB,CAAA;AAuBrC,MAAM,OAAO,kBAAkB;IAOV;IACA;IAPnB,uEAAuE;IAC/D,YAAY,GAAG,IAAI,GAAG,EAAsB,CAAA;IACpD,kFAAkF;IAC1E,aAAa,GAAG,IAAI,GAAG,EAAU,CAAA;IAEzC,YACmB,aAA4B,EAC5B,UAAsB;QADtB,kBAAa,GAAb,aAAa,CAAe;QAC5B,eAAU,GAAV,UAAU,CAAY;QAEvC,uBAAuB,CAAC,gBAAgB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAA;IACxE,CAAC;IAED;;;;OAIG;IACK,eAAe;QACrB,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC;YAAE,OAAM;QACzC,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,oDAAoD,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAC/G,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YAC7C,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE;gBAC9B,IAAI,EAAE,mBAAmB,CAAC,KAAK;gBAC/B,UAAU,EAAE,iBAAiB,CAAC,iBAAiB;gBAC/C,IAAI,EAAE,EAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAC;aAC7C,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAA;QAC1B,KAAK,iBAAiB,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACnD,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,8CAA8C,EAAE,GAAG,CAAC,CAAA;QAC9E,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,2FAA2F;IAC3F,YAAY,CAAC,WAAmB;QAC9B,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IAC5C,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,WAAmB;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAChD,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,EAAE,CAAA;YACP,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;QACvC,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,WAAmB;QAC7B,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;QAC9B,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC;YAAE,OAAM;QACnD,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC;YAAE,OAAM;QACvC,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,KAAK,WAAW,mDAAmD,CAAC,CAAA;QAC1F,uBAAuB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;QACxC,KAAK,iBAAiB,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACnD,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,2CAA2C,EAAE,GAAG,CAAC,CAAA;QAC3E,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,WAAmB,EAAE,OAAgC,EAAE,SAAkB;QACzF,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,gCAAgC,WAAW,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;QAE7F,yEAAyE;QACzE,MAAM,QAAQ,GAAG,OAAO,CAAC,KAA0D,CAAA;QACnF,MAAM,KAAK,GAAsC,EAAE,CAAA;QACnD,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;gBAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;gBAC3B,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,EAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAC,CAAC,CAAA;YACxF,CAAC;QACH,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YAC/B,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,EAAC,GAAG,EAAE,GAAG,EAAC,CAAC,CAAA;QAC1E,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;gBAC/B,OAAO,EAAE,2BAA2B;aACrC,CAAC,CAAA;YACF,OAAM;QACR,CAAC;QACD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;QACxB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;QACxB,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,IAAI,CAAA;QAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;QAChD,MAAM,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;QAChF,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;QACxE,MAAM,QAAQ,GAAG,OAAO,CAAC,KAA4C,CAAA;QACrE,MAAM,KAAK,GAAG,QAAQ;YACpB,CAAC,CAAC;gBACE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,KAAK,IAAI;gBACpC,KAAK,EAAE,QAAQ,CAAC,KAAK,KAAK,IAAI;gBAC9B,OAAO,EAAE,QAAQ,CAAC,OAAO,KAAK,IAAI;aACnC;YACH,CAAC,CAAC,SAAS,CAAA;QACb,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAA;QACzD,MAAM,uBAAuB,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;QAEnG,MAAM,UAAU,GAAG,iBAAiB,CAAA;QACpC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;gBAC/B,OAAO,EAAE,2CAA2C;aACrD,CAAC,CAAA;YACF,OAAM;QACR,CAAC;QAED,2EAA2E;QAC3E,qDAAqD;QACrD,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YACxC,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC,MAAiB,EAAE,EAAE;gBAC5D,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE;oBAC9B,IAAI,EAAE,mBAAmB,CAAC,KAAK;oBAC/B,UAAU,EAAE,iBAAiB,CAAC,iBAAiB;oBAC/C,IAAI,EAAE,MAAM;iBACb,CAAC,CAAA;gBACF,+DAA+D;gBAC/D,+DAA+D;gBAC/D,kBAAkB;gBAClB,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBACzD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;oBACtC,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;wBAClC,uBAAuB,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAA;oBAC9D,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAA;YACF,oEAAoE;YACpE,wEAAwE;YACxE,gCAAgC;YAChC,MAAM,QAAQ,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC,GAAgB,EAAE,EAAE;gBACnE,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE;oBAC9B,IAAI,EAAE,mBAAmB,CAAC,KAAK;oBAC/B,UAAU,EAAE,iBAAiB,CAAC,eAAe;oBAC7C,IAAI,EAAE;wBACJ,GAAG,EAAE,GAAG,CAAC,GAAG;wBACZ,GAAG,EAAE,GAAG,CAAC,GAAG;wBACZ,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,SAAS;wBACnC,SAAS,EAAE,GAAG,CAAC,SAAS;qBACzB;iBACF,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;YACF,MAAM,UAAU,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC,KAAe,EAAE,EAAE;gBACjE,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE;oBAC9B,IAAI,EAAE,mBAAmB,CAAC,KAAK;oBAC/B,UAAU,EAAE,iBAAiB,CAAC,gBAAgB;oBAC9C,IAAI,EAAE,KAAK;iBACZ,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;YACF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE;gBACtC,QAAQ,EAAE,CAAA;gBACV,QAAQ,EAAE,CAAA;gBACV,UAAU,EAAE,CAAA;YACd,CAAC,CAAC,CAAA;QACJ,CAAC;QAED,wEAAwE;QACxE,wEAAwE;QACxE,8CAA8C;QAC9C,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,UAAU,CAAC,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;YAC5E,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,uCAAuC,WAAW,EAAE,CAAC,CAAA;YAC3E,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,EAAE,CAAA;YACzC,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,EAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAC,CAAC,CAAA;YAClF,OAAM;QACR,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CACnC,EAAC,GAAG,EAAE,GAAG,EAAC,EACV,EAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,uBAAuB,EAAC,CACzE,CAAA;YACD,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;gBACd,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;gBACnC,kEAAkE;gBAClE,gDAAgD;gBAChD,uBAAuB,CAAC,WAAW,CAAC,WAAW,CAAC,CAAA;YAClD,CAAC;YACD,mEAAmE;YACnE,mEAAmE;YACnE,wEAAwE;YACxE,kEAAkE;YAClE,qDAAqD;YACrD,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,2BAA2B,EAAE,GAAG,CAAC,CAAA;YACzD,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;gBAC/B,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB;aACvE,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,WAAmB,EAAE,SAAkB;QACtD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;YAChD,IAAI,KAAK,EAAE,CAAC;gBACV,KAAK,EAAE,CAAA;gBACP,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;YACvC,CAAC;YACD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;YACtC,uEAAuE;YACvE,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBAClC,uBAAuB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;gBACxC,MAAM,UAAU,GAAG,iBAAiB,CAAA;gBACpC,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAC,EAAE,EAAE,IAAI,EAAC,CAAA;gBAChE,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;YACvD,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,EAAC,EAAE,EAAE,IAAI,EAAC,EAAE,SAAS,CAAC,CAAA;YACtE,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,0BAA0B,EAAE,GAAG,CAAC,CAAA;YACxD,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;gBAC/B,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB;aACtE,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,WAAmB,EAAE,OAAgC,EAAE,SAAkB;QAC3F,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;YAC9C,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAA;YACjF,MAAM,UAAU,GAAG,iBAAiB,CAAA;YACpC,MAAM,MAAM,GAAG,UAAU;gBACvB,CAAC,CAAC,MAAM,UAAU,CAAC,iBAAiB,CAAC,YAAY,CAAC;gBAClD,CAAC,CAAC,EAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,mCAAmC,EAAC,CAAA;YAC3D,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,6BAA6B,EAAE,GAAG,CAAC,CAAA;YAC3D,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;gBAC/B,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,0BAA0B;aACzE,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,sBAAsB,CAC1B,WAAmB,EACnB,OAAgC,EAChC,SAAkB;QAElB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,KAAK,IAAI,CAAA;YACxC,MAAM,UAAU,GAAG,iBAAiB,CAAA;YACpC,MAAM,MAAM,GAAG,UAAU;gBACvB,CAAC,CAAC,MAAM,UAAU,CAAC,sBAAsB,CAAC,OAAO,CAAC;gBAClD,CAAC,CAAC,EAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,mCAAmC,EAAC,CAAA;YAC3D,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,4CAA4C,EAAE,GAAG,CAAC,CAAA;YAC1E,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;gBAC/B,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,yCAAyC;aACxF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,sBAAsB,CAC1B,WAAmB,EACnB,OAAgC,EAChC,SAAkB;QAElB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,KAAK,IAAI,CAAA;YACxC,MAAM,UAAU,GAAG,iBAAiB,CAAA;YACpC,MAAM,MAAM,GAAG,UAAU;gBACvB,CAAC,CAAC,MAAM,UAAU,CAAC,gBAAgB,CAAC,OAAO,CAAC;gBAC5C,CAAC,CAAC,EAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,mCAAmC,EAAC,CAAA;YAC3D,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,sCAAsC,EAAE,GAAG,CAAC,CAAA;YACpE,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;gBAC/B,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,mCAAmC;aAClF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,cAAc,CAAC,WAAmB,EAAE,SAAkB;QACpD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,WAAW,EAAE,IAAI,IAAI,CAAA;QACxD,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,EAAC,KAAK,EAAE,QAAQ,EAAC,CAAC,CAAA;IAClE,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,WAAmB,EAAE,SAAkB;QACnE,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,iBAAiB,CAAA;YACpC,MAAM,MAAM,GAAG,UAAU;gBACvB,CAAC,CAAC,MAAM,UAAU,CAAC,iBAAiB,EAAE;gBACtC,CAAC,CAAC,EAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,mCAAmC,EAAC,CAAA;YAC5E,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,uCAAuC,EAAE,GAAG,CAAC,CAAA;YACrE,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;gBAC/B,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,oCAAoC;aACnF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,WAAmB,EAAE,OAAgC,EAAE,SAAkB;QAChG,IAAI,CAAC;YACH,gEAAgE;YAChE,wEAAwE;YACxE,qEAAqE;YACrE,sCAAsC;YACtC,IAAI,iBAAiB,CAAC,cAAc,EAAE,EAAE,CAAC;gBACvC,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;gBAC3D,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;oBACb,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,EAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE,EAAC,CAAC,CAAA;oBACrF,OAAM;gBACR,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,qDAAqD,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;YAC5F,CAAC;YAED,uEAAuE;YACvE,uEAAuE;YACvE,oEAAoE;YACpE,MAAM,EAAC,MAAM,EAAC,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,OAAgB,CAAC,CAAA;YAC3E,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,EAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAC,CAAC,CAAA;QACnE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,kCAAkC,EAAE,GAAG,CAAC,CAAA;YAChE,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;gBAC/B,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,+BAA+B;aAC9E,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,oBAAoB,CAAC,WAAmB,EAAE,OAAgC,EAAE,SAAkB;QAClG,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YAC/B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnD,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;oBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;oBAC/B,OAAO,EAAE,kBAAkB;iBAC5B,CAAC,CAAA;gBACF,OAAM;YACR,CAAC;YACD,kEAAkE;YAClE,8DAA8D;YAC9D,IAAI,iBAAiB,CAAC,cAAc,EAAE,EAAE,CAAC;gBACvC,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,kBAAkB,CAAC,EAAC,GAAG,EAAE,GAAG,EAAC,CAAC,CAAA;gBACpE,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;oBACb,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE;wBAC5C,EAAE,EAAE,IAAI;wBACR,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;wBACxB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;qBAC/B,CAAC,CAAA;oBACF,OAAM;gBACR,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,uDAAuD,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;YAC9F,CAAC;YAED,MAAM,EAAC,IAAI,EAAE,OAAO,EAAC,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,cAAc,CAAC,EAAC,GAAG,EAAE,GAAG,EAAC,CAAC,CAAA;YAChF,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,EAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAC,CAAC,CAAA;QAC1E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,oCAAoC,EAAE,GAAG,CAAC,CAAA;YAClE,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;gBAC/B,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,iCAAiC;aAChF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,uBAAuB,CAC3B,WAAmB,EACnB,OAAgC,EAChC,SAAkB;QAElB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;YACpE,MAAM,YAAY,GAAG,OAAO,OAAO,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAA;YACzF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;YAEzC,IAAI,iBAAiB,CAAC,cAAc,EAAE,EAAE,CAAC;gBACvC,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,iBAAiB,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,CAAC,CAAA;gBAClF,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;oBACb,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,EAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE,EAAC,CAAC,CAAA;oBAC/F,OAAM;gBACR,CAAC;gBACD,sEAAsE;gBACtE,mEAAmE;gBACnE,YAAY;gBACZ,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,0DAA0D,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;YACjG,CAAC;YAED,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAC,KAAK,EAAE,IAAI,EAAE,YAAY,EAAC,CAAC,CAAA;YAClG,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,EAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC,CAAA;QACxE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,uCAAuC,EAAE,GAAG,CAAC,CAAA;YACrE,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;gBAC/B,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,oCAAoC;aACnF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,kBAAkB,CAAC,WAAmB,EAAE,OAAgC,EAAE,SAAkB;QAChG,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;YAC1E,MAAM,YAAY,GAAG,OAAO,OAAO,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAA;YACzF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;oBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;oBAC/B,OAAO,EAAE,kBAAkB;iBAC5B,CAAC,CAAA;gBACF,OAAM;YACR,CAAC;YAED,IAAI,iBAAiB,CAAC,cAAc,EAAE,EAAE,CAAC;gBACvC,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;gBACzE,IAAI,KAAK,CAAC,EAAE,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;oBAC5B,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,EAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAC,CAAC,CAAA;oBAC7E,OAAM;gBACR,CAAC;gBACD,uEAAuE;gBACvE,mEAAmE;gBACnE,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;oBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;oBAC/B,OAAO,EAAE,KAAK,CAAC,KAAK,IAAI,+BAA+B;iBACxD,CAAC,CAAA;gBACF,OAAM;YACR,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,YAAY,CAAC,EAAC,OAAO,EAAE,YAAY,EAAC,CAAC,CAAA;YACjF,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,EAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAC,CAAC,CAAA;QAClE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,kCAAkC,EAAE,GAAG,CAAC,CAAA;YAChE,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACxD,IAAI,EAAE,gBAAgB,CAAC,QAAQ;gBAC/B,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,+BAA+B;aAC9E,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,yFAAyF;IACjF,SAAS,CAAC,GAAY;QAC5B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAA;QACrD,MAAM,GAAG,GAAG,GAA8B,CAAA;QAC1C,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC3B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,SAAS,CAAA;QACpE,OAAO,EAAC,GAAG,EAAE,GAAG,EAAC,CAAA;IACnB,CAAC;CACF","sourcesContent":["/**\n * NavigationHandlers — turn-by-turn navigation request handlers for\n * LocalMiniappRuntime. Extracted from LocalMiniappRuntime so the\n * navigation surface (Google Maps Navigation SDK adapter, multi-stop\n * routes, deviation simulator, dev toggles, road-snapped GPS streaming)\n * lives in one file the reviewer can read in isolation.\n *\n * Wire-up: LocalMiniappRuntime owns one instance, constructed with\n * callbacks for sending results / events back to the miniapp. The\n * dispatcher's switch statement delegates each `NAVIGATION_*` case to a\n * handler here. Cross-cutting hooks (cleanup on disconnect, location-\n * stream gating during a trip) are exposed via {@link onDisconnect} and\n * {@link isTripActive}.\n *\n * State owned here:\n * - navListeners: per-package unsubscribers for the nav-update +\n * road-snapped-location + route streams. Detached on disconnect,\n * reattached on the next NAVIGATION_START from the same package.\n * - activeNavApps: packages with a live nav session. Used by the\n * dispatcher to gate raw background-GPS forwards (we don't want the\n * unsnapped fix interleaving with the simulator's snapped output\n * during a trip).\n */\n\nimport {type NavLocation, type NavRoute, type NavUpdate} from \"../runtime/config\"\nimport {cloudClientService} from \"./CloudClientService\"\nimport nativeNavigationService from \"./NativeNavigationService\"\nimport navigationService from \"./NavigationService\"\nimport {MiniappErrorCode, MiniappResponseType, MiniappStreamType} from \"@glassly/miniapp\"\n\nconst LOG_TAG = \"LocalMiniappRuntime\"\n\n/**\n * Shape of the per-miniapp envelope sender — matches\n * LocalMiniappRuntime.sendToMiniapp's signature.\n */\ntype SendToMiniapp = (\n packageName: string,\n envelope: {type: MiniappResponseType; streamType?: MiniappStreamType; data?: unknown},\n) => void\n\n/**\n * Shape of the request-result sender — matches\n * LocalMiniappRuntime.sendResult's signature.\n */\ntype SendResult = (\n packageName: string,\n requestId: string | undefined,\n ok: boolean,\n result?: unknown,\n error?: {code: MiniappErrorCode; message: string},\n) => void\n\nexport class NavigationHandlers {\n /** packageName → unsubscribe fn for that app's nav event forwarder. */\n private navListeners = new Map<string, () => void>()\n /** Set of packageNames that have called navigation.start() and not yet stop(). */\n private activeNavApps = new Set<string>()\n\n constructor(\n private readonly sendToMiniapp: SendToMiniapp,\n private readonly sendResult: SendResult,\n ) {\n nativeNavigationService.setOnGlassesExit(() => this.stopFromGlasses())\n }\n\n /**\n * The wearer exited nav mode on the glasses — end the trip: stop the native\n * navigator and tell each active nav app via a \"cancelled\" update so it can\n * reset its own trip state.\n */\n private stopFromGlasses(): void {\n if (this.activeNavApps.size === 0) return\n console.log(`${LOG_TAG}: nav mode exited on glasses — stopping trip for ${[...this.activeNavApps].join(\", \")}`)\n for (const packageName of this.activeNavApps) {\n this.sendToMiniapp(packageName, {\n type: MiniappResponseType.EVENT,\n streamType: MiniappStreamType.NAVIGATION_UPDATE,\n data: {kind: \"cancelled\", reason: \"glasses\"},\n })\n }\n this.activeNavApps.clear()\n void navigationService.stop().catch((err: unknown) => {\n console.error(`${LOG_TAG}: navigation stop after glasses exit failed:`, err)\n })\n }\n\n /** True iff a trip is currently active for the package (used to gate raw-GPS forwards). */\n isTripActive(packageName: string): boolean {\n return this.activeNavApps.has(packageName)\n }\n\n /**\n * Detach the per-app nav event forwarder. Called when the mini-app\n * disconnects. The native nav session is left running so the user can\n * reopen the app and reattach without losing their trip; `activeNavApps`\n * is kept intact for the same reason.\n */\n onDisconnect(packageName: string): void {\n const unsub = this.navListeners.get(packageName)\n if (unsub) {\n unsub()\n this.navListeners.delete(packageName)\n }\n }\n\n /**\n * The user closed/disabled the mini-app (not a crash-respawn). Unlike\n * {@link onDisconnect}, this ends the trip: the glasses leave native nav\n * mode and the phone navigator stops once no other app is navigating.\n */\n onAppClosed(packageName: string): void {\n this.onDisconnect(packageName)\n if (!this.activeNavApps.delete(packageName)) return\n if (this.activeNavApps.size > 0) return\n console.log(`${LOG_TAG}: ${packageName} closed with an active trip — stopping navigation`)\n nativeNavigationService.onTripEnd(false)\n void navigationService.stop().catch((err: unknown) => {\n console.error(`${LOG_TAG}: navigation stop after app close failed:`, err)\n })\n }\n\n async handleStart(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n console.log(`${LOG_TAG}: handleNavigationStart from ${packageName}`, JSON.stringify(payload))\n\n // v2 wire shape sends `stops`; v1 shape sends bare lat/lng. Accept both.\n const rawStops = payload.stops as Array<{lat?: unknown; lng?: unknown}> | undefined\n const stops: Array<{lat: number; lng: number}> = []\n if (Array.isArray(rawStops)) {\n for (const s of rawStops) {\n const sLat = Number(s?.lat)\n const sLng = Number(s?.lng)\n if (Number.isFinite(sLat) && Number.isFinite(sLng)) stops.push({lat: sLat, lng: sLng})\n }\n }\n if (stops.length === 0) {\n const lat = Number(payload.lat)\n const lng = Number(payload.lng)\n if (Number.isFinite(lat) && Number.isFinite(lng)) stops.push({lat, lng})\n }\n if (stops.length === 0) {\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: \"stops or lat/lng required\",\n })\n return\n }\n const lat = stops[0].lat\n const lng = stops[0].lng\n const simulate = payload.simulate === true\n const speedNum = Number(payload.speedMultiplier)\n const speedMultiplier = Number.isFinite(speedNum) && speedNum > 0 ? speedNum : 5\n const mode = typeof payload.mode === \"string\" ? payload.mode : \"walking\"\n const avoidRaw = payload.avoid as Record<string, unknown> | undefined\n const avoid = avoidRaw\n ? {\n highways: avoidRaw.highways === true,\n tolls: avoidRaw.tolls === true,\n ferries: avoidRaw.ferries === true,\n }\n : undefined\n const missedRaw = Number(payload.missedTurnRerouteMeters)\n const missedTurnRerouteMeters = Number.isFinite(missedRaw) && missedRaw > 0 ? missedRaw : undefined\n\n const navigation = navigationService\n if (!navigation) {\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: \"navigation adapter not configured on host\",\n })\n return\n }\n\n // Reattach the per-app event forwarder (it may have been detached when the\n // mini-app closed its UI without stopping the trip).\n if (!this.navListeners.has(packageName)) {\n const unsubNav = navigation.addListener((update: NavUpdate) => {\n this.sendToMiniapp(packageName, {\n type: MiniappResponseType.EVENT,\n streamType: MiniappStreamType.NAVIGATION_UPDATE,\n data: update,\n })\n // Trip ended naturally — keep the forwarder alive (miniapp may\n // restart nav) but remove from active set so stop() accounting\n // stays accurate.\n if (update.kind === \"arrived\" || update.kind === \"error\") {\n this.activeNavApps.delete(packageName)\n if (this.activeNavApps.size === 0) {\n nativeNavigationService.onTripEnd(update.kind === \"arrived\")\n }\n }\n })\n // Forward the nav-SDK's road-snapped GPS fixes as a location_update\n // stream, so the miniapp's existing session.events.onLocation(...) just\n // works while a trip is active.\n const unsubLoc = navigation.addLocationListener((loc: NavLocation) => {\n this.sendToMiniapp(packageName, {\n type: MiniappResponseType.EVENT,\n streamType: MiniappStreamType.LOCATION_UPDATE,\n data: {\n lat: loc.lat,\n lng: loc.lng,\n accuracy: loc.accuracy ?? undefined,\n timestamp: loc.timestamp,\n },\n })\n })\n const unsubRoute = navigation.addRouteListener((route: NavRoute) => {\n this.sendToMiniapp(packageName, {\n type: MiniappResponseType.EVENT,\n streamType: MiniappStreamType.NAVIGATION_ROUTE,\n data: route,\n })\n })\n this.navListeners.set(packageName, () => {\n unsubNav()\n unsubLoc()\n unsubRoute()\n })\n }\n\n // If a trip is already active for this app (user closed the UI and came\n // back), reuse the running session — replay current snapshot and return\n // ok without restarting the native navigator.\n if (this.activeNavApps.has(packageName) && navigation.getState() !== \"idle\") {\n console.log(`${LOG_TAG}: resuming existing nav session for ${packageName}`)\n const snapshot = navigation.getSnapshot()\n this.sendResult(packageName, requestId, true, {ok: true, resumed: true, snapshot})\n return\n }\n\n try {\n const result = await navigation.start(\n {lat, lng},\n {simulate, speedMultiplier, stops, mode, avoid, missedTurnRerouteMeters},\n )\n if (result.ok) {\n this.activeNavApps.add(packageName)\n // Glasses with a firmware-rendered nav UI (G2) enter their native\n // navigation mode for the duration of the trip.\n nativeNavigationService.onTripStart(packageName)\n }\n // A refused start (`{ok: false, error}` from the token gate or the\n // native navigator) is request DATA, not a wire failure: the SDK's\n // navigation.start() contract is \"resolves {ok, error?}, never throws\".\n // Sending it as ok:false on the wire made the SDK reject with its\n // generic \"Unknown error\" and drop the real message.\n this.sendResult(packageName, requestId, true, result)\n } catch (err) {\n console.error(`${LOG_TAG}: navigation start error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation start error\",\n })\n }\n }\n\n async handleStop(packageName: string, requestId?: string): Promise<void> {\n try {\n const unsub = this.navListeners.get(packageName)\n if (unsub) {\n unsub()\n this.navListeners.delete(packageName)\n }\n this.activeNavApps.delete(packageName)\n // Only stop the native trip when no other miniapp is still navigating.\n if (this.activeNavApps.size === 0) {\n nativeNavigationService.onTripEnd(false)\n const navigation = navigationService\n const result = navigation ? await navigation.stop() : {ok: true}\n this.sendResult(packageName, requestId, true, result)\n } else {\n this.sendResult(packageName, requestId, true, {ok: true}, undefined)\n }\n } catch (err) {\n console.error(`${LOG_TAG}: navigation stop error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation stop error\",\n })\n }\n }\n\n async handleDeviate(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n try {\n const offsetNum = Number(payload.offsetMeters)\n const offsetMeters = Number.isFinite(offsetNum) && offsetNum > 0 ? offsetNum : 20\n const navigation = navigationService\n const result = navigation\n ? await navigation.simulateDeviation(offsetMeters)\n : {ok: false, error: \"navigation adapter not configured\"}\n this.sendResult(packageName, requestId, true, result)\n } catch (err) {\n console.error(`${LOG_TAG}: navigation deviate error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation deviate error\",\n })\n }\n }\n\n async handleSetWrongSidewalk(\n packageName: string,\n payload: Record<string, unknown>,\n requestId?: string,\n ): Promise<void> {\n try {\n const enabled = payload.enabled === true\n const navigation = navigationService\n const result = navigation\n ? await navigation.setWrongSidewalkOffset(enabled)\n : {ok: false, error: \"navigation adapter not configured\"}\n this.sendResult(packageName, requestId, true, result)\n } catch (err) {\n console.error(`${LOG_TAG}: navigation setWrongSidewalkOffset error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation setWrongSidewalkOffset error\",\n })\n }\n }\n\n async handleSetSkipCrossings(\n packageName: string,\n payload: Record<string, unknown>,\n requestId?: string,\n ): Promise<void> {\n try {\n const enabled = payload.enabled === true\n const navigation = navigationService\n const result = navigation\n ? await navigation.setSkipCrossings(enabled)\n : {ok: false, error: \"navigation adapter not configured\"}\n this.sendResult(packageName, requestId, true, result)\n } catch (err) {\n console.error(`${LOG_TAG}: navigation setSkipCrossings error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation setSkipCrossings error\",\n })\n }\n }\n\n handleGetState(packageName: string, requestId?: string): void {\n const snapshot = navigationService.getSnapshot() ?? null\n this.sendResult(packageName, requestId, true, {state: snapshot})\n }\n\n async handleRequestPermission(packageName: string, requestId?: string): Promise<void> {\n try {\n const navigation = navigationService\n const result = navigation\n ? await navigation.requestPermission()\n : {ok: false, accepted: false, error: \"navigation adapter not configured\"}\n this.sendResult(packageName, requestId, true, result)\n } catch (err) {\n console.error(`${LOG_TAG}: navigation requestPermission error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation requestPermission error\",\n })\n }\n }\n\n async handleComputeRoute(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n try {\n // With the user's own Mapbox key (Settings > API Keys), compute\n // on-device so routing works without the cloud and bills their account.\n // Without one, go through the v2 cloud maps proxy — org-token Mapbox\n // usage only ever happens cloud-side.\n if (navigationService.hasMapboxToken()) {\n const local = await navigationService.computeRoute(payload)\n if (local.ok) {\n this.sendResult(packageName, requestId, true, {ok: true, routes: local.routes ?? []})\n return\n }\n console.warn(`${LOG_TAG}: local computeRoute failed, falling back to cloud:`, local.error)\n }\n\n // Computed in the v2 cloud (provider-abstracted maps service). The SDK\n // payload shape ({origin, stops, mode, avoid, alternatives}) is the v2\n // DirectionsRequest field-for-field, so it passes straight through.\n const {routes} = await cloudClientService.maps.directions(payload as never)\n this.sendResult(packageName, requestId, true, {ok: true, routes})\n } catch (err) {\n console.error(`${LOG_TAG}: navigation computeRoute error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation computeRoute error\",\n })\n }\n }\n\n /**\n * Reverse-geocode a coordinate into a short road name + full formatted\n * address. Backs the SDK pivot engine's road-name fallback (`road`) and the\n * navigation miniapp's dropped-pin / POI-tap labels (`address`). Always\n * resolves with `{ok, road?, address?}` — a missing road/address is\n * `{ok: true, road: null, address: null}`, not an error.\n */\n async handleReverseGeocode(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n try {\n const lat = Number(payload.lat)\n const lng = Number(payload.lng)\n if (!Number.isFinite(lat) || !Number.isFinite(lng)) {\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: \"lat/lng required\",\n })\n return\n }\n // With the user's own Mapbox key, resolve on-device so this works\n // without the cloud; otherwise use the v2 cloud maps service.\n if (navigationService.hasMapboxToken()) {\n const local = await navigationService.reverseGeocodeRoad({lat, lng})\n if (local.ok) {\n this.sendResult(packageName, requestId, true, {\n ok: true,\n road: local.road ?? null,\n address: local.address ?? null,\n })\n return\n }\n console.warn(`${LOG_TAG}: local reverseGeocode failed, falling back to cloud:`, local.error)\n }\n\n const {road, address} = await cloudClientService.maps.reverseGeocode({lat, lng})\n this.sendResult(packageName, requestId, true, {ok: true, road, address})\n } catch (err) {\n console.error(`${LOG_TAG}: navigation reverseGeocode error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation reverseGeocode error\",\n })\n }\n }\n\n /**\n * Type-ahead place search. Runs on-device against Mapbox Search Box when the\n * user saved their own key (Settings > API Keys) — that key exists precisely\n * so search works without the cloud — and falls back to the v2 cloud maps\n * service otherwise. Resolves `{ok: true, suggestions}` — an empty query or no\n * matches is `{ok: true, suggestions: []}`, not an error.\n */\n async handlePlaceAutocomplete(\n packageName: string,\n payload: Record<string, unknown>,\n requestId?: string,\n ): Promise<void> {\n try {\n const query = typeof payload.query === \"string\" ? payload.query : \"\"\n const sessionToken = typeof payload.sessionToken === \"string\" ? payload.sessionToken : \"\"\n const near = this.parseNear(payload.near)\n\n if (navigationService.hasMapboxToken()) {\n const local = await navigationService.placeAutocomplete(query, near, sessionToken)\n if (local.ok) {\n this.sendResult(packageName, requestId, true, {ok: true, suggestions: local.suggestions ?? []})\n return\n }\n // A token is set but the direct call failed (bad key, offline, Mapbox\n // error). Fall through to the cloud rather than failing the search\n // outright.\n console.warn(`${LOG_TAG}: local placeAutocomplete failed, falling back to cloud:`, local.error)\n }\n\n const {suggestions} = await cloudClientService.maps.placeAutocomplete({query, near, sessionToken})\n this.sendResult(packageName, requestId, true, {ok: true, suggestions})\n } catch (err) {\n console.error(`${LOG_TAG}: navigation placeAutocomplete error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation placeAutocomplete error\",\n })\n }\n }\n\n /**\n * Resolve a suggestion (`placeId` + `sessionToken`) to a full place with\n * coordinates. Takes the same on-device-vs-cloud branch as\n * {@link handlePlaceAutocomplete}: the `placeId` and session token come from\n * whichever provider produced the suggestion, so both calls must run against\n * the same one. Resolves `{ok: true, place}`.\n */\n async handlePlaceDetails(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n try {\n const placeId = typeof payload.placeId === \"string\" ? payload.placeId : \"\"\n const sessionToken = typeof payload.sessionToken === \"string\" ? payload.sessionToken : \"\"\n if (!placeId) {\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: \"placeId required\",\n })\n return\n }\n\n if (navigationService.hasMapboxToken()) {\n const local = await navigationService.placeDetails(placeId, sessionToken)\n if (local.ok && local.place) {\n this.sendResult(packageName, requestId, true, {ok: true, place: local.place})\n return\n }\n // Don't fall back to the cloud here: this `placeId` came from a Mapbox\n // Search Box suggestion and is not resolvable by another provider.\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: local.error ?? \"navigation placeDetails error\",\n })\n return\n }\n\n const place = await cloudClientService.maps.placeDetails({placeId, sessionToken})\n this.sendResult(packageName, requestId, true, {ok: true, place})\n } catch (err) {\n console.error(`${LOG_TAG}: navigation placeDetails error:`, err)\n this.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.INTERNAL,\n message: err instanceof Error ? err.message : \"navigation placeDetails error\",\n })\n }\n }\n\n /** Coerce an inbound `near` payload to a {lat,lng}, or undefined when absent/invalid. */\n private parseNear(raw: unknown): {lat: number; lng: number} | undefined {\n if (!raw || typeof raw !== \"object\") return undefined\n const obj = raw as Record<string, unknown>\n const lat = Number(obj.lat)\n const lng = Number(obj.lng)\n if (!Number.isFinite(lat) || !Number.isFinite(lng)) return undefined\n return {lat, lng}\n }\n}\n"]}
@@ -30,7 +30,7 @@ class NavigationService {
30
30
  lastManeuver = null;
31
31
  /** Trip configuration captured at start(), surfaced via getState(). */
32
32
  tripStops = [];
33
- tripMode = "driving";
33
+ tripMode = "walking";
34
34
  constructor() { }
35
35
  static getInstance() {
36
36
  if (!NavigationService.instance) {
@@ -131,7 +131,7 @@ class NavigationService {
131
131
  simulate: options?.simulate ?? false,
132
132
  speedMultiplier: options?.speedMultiplier ?? 5,
133
133
  stops: options?.stops,
134
- mode: options?.mode ?? "driving",
134
+ mode: options?.mode ?? "walking",
135
135
  avoid: options?.avoid,
136
136
  missedTurnRerouteMeters: options?.missedTurnRerouteMeters,
137
137
  });
@@ -139,12 +139,12 @@ class NavigationService {
139
139
  console.warn(`${LOG_TAG}: start failed — ${result.error}`);
140
140
  this.state = "idle";
141
141
  this.tripStops = [];
142
- this.tripMode = "driving";
142
+ this.tripMode = "walking";
143
143
  }
144
144
  else {
145
145
  this.state = "navigating";
146
146
  this.tripStops = options?.stops ?? [{ lat: coords.lat, lng: coords.lng }];
147
- this.tripMode = options?.mode ?? "driving";
147
+ this.tripMode = options?.mode ?? "walking";
148
148
  }
149
149
  return result;
150
150
  }
@@ -179,7 +179,7 @@ class NavigationService {
179
179
  this.lastRoute = null;
180
180
  this.lastManeuver = null;
181
181
  this.tripStops = [];
182
- this.tripMode = "driving";
182
+ this.tripMode = "walking";
183
183
  return result;
184
184
  }
185
185
  /**
@@ -395,7 +395,7 @@ function mapboxToken() {
395
395
  async function computeRouteViaRoutesApi(payload) {
396
396
  const origin = payload.origin;
397
397
  const stopsRaw = payload.stops;
398
- const mode = (typeof payload.mode === "string" ? payload.mode : "driving").toLowerCase();
398
+ const mode = (typeof payload.mode === "string" ? payload.mode : "walking").toLowerCase();
399
399
  const alt = Number(payload.alternatives);
400
400
  const alternatives = Number.isFinite(alt) && alt > 0 ? alt : 1;
401
401
  const avoid = payload.avoid ?? {};
@@ -1 +1 @@
1
- {"version":3,"file":"NavigationService.js","sourceRoot":"","sources":["../../src/services/NavigationService.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * NavigationService\n *\n * Thin singleton wrapper around the native Mapbox Navigation SDK exposed\n * by the `crust` Expo module.\n *\n * Mini apps will eventually subscribe through the mini app SDK, which\n * routes via LocalMiniappRuntime and ultimately calls into here. For now,\n * this is also called directly by the developer-settings test button.\n *\n * Works on both Android and iOS via the native Mapbox Navigation SDK.\n */\n\nimport CrustModule from \"@glassly/crust\"\n\nimport {resolveMapboxAccessToken, resolveMapboxRenderToken, userMapboxApiKey} from \"./MapboxTokenService\"\nimport {decodePolyline, parseDurationSeconds} from \"./navigation/routesApiCodec\"\nimport {resolveStepRoads} from \"./navigation/roadNameResolver\"\nimport {BgTimer} from \"../utils/timers\"\n\nconst LOG_TAG = \"NAV_SERVICE\"\n\nexport type NavManeuver = {\n kind: \"maneuver\"\n /**\n * Categorical type of the upcoming maneuver. One of: STRAIGHT,\n * SLIGHT_LEFT, SLIGHT_RIGHT, TURN_LEFT, TURN_RIGHT, SHARP_LEFT,\n * SHARP_RIGHT, U_TURN, ARRIVE.\n */\n maneuverType: string\n distanceMeters: number\n /** Road the user is currently on. Null if the SDK didn't supply one. */\n fromRoad?: string | null\n /** Road the user will be on after the maneuver. Null if the SDK didn't supply one. */\n toRoad?: string | null\n distanceToDestinationMeters?: number\n timeToDestinationSeconds?: number\n currentSpeedMps?: number | null\n speedLimitMps?: number | null\n routeHeadingDeg?: number | null\n}\n\nexport type NavOffRoute = {\n kind: \"off_route\"\n offRouteDistanceMeters: number\n}\n\nexport type NavRerouting = {kind: \"rerouting\"}\nexport type NavArrived = {kind: \"arrived\"}\nexport type NavError = {kind: \"error\"; message: string}\n\nexport type NavUpdate = NavManeuver | NavOffRoute | NavRerouting | NavArrived | NavError\n\nexport type NavListener = (update: NavUpdate) => void\n\nexport type NavLocation = {\n lat: number\n lng: number\n accuracy: number | null\n timestamp: number\n}\nexport type NavLocationListener = (loc: NavLocation) => void\n\nexport type NavRouteStep = {\n lat: number\n lng: number\n routeIndex: number\n road: string | null\n maneuver: string\n distanceMeters: number\n}\nexport type NavRoute = {\n points: Array<{lat: number; lng: number}>\n steps?: NavRouteStep[]\n}\nexport type NavRouteListener = (route: NavRoute) => void\n\nexport type NavState = \"idle\" | \"navigating\" | \"rerouting\" | \"arrived\"\n\n/**\n * Snapshot of the active trip — fed to miniapps that open mid-trip via\n * `navigation.getState()`. Mirrors the SDK's NavState shape closely; the\n * runtime keeps it strictly in sync as nav events arrive.\n */\nexport type NavTripSnapshot = {\n active: boolean\n mode?: string\n stops?: Array<{lat: number; lng: number}>\n currentStopIndex?: number\n route?: NavRoute\n maneuver?: NavManeuver\n distanceToDestinationMeters?: number\n timeToDestinationSeconds?: number\n currentSpeedMps?: number | null\n speedLimitMps?: number | null\n}\n\nclass NavigationService {\n private static instance: NavigationService | null = null\n private listeners = new Set<NavListener>()\n private locationListeners = new Set<NavLocationListener>()\n private routeListeners = new Set<NavRouteListener>()\n private subs: Array<{remove: () => void}> = []\n private state: NavState = \"idle\"\n /** Last emitted route — replayed to late subscribers so they get the\n * current geometry immediately. */\n private lastRoute: NavRoute | null = null\n /** Last maneuver event observed — used to hydrate getState() on mid-trip mount. */\n private lastManeuver: NavManeuver | null = null\n /** Trip configuration captured at start(), surfaced via getState(). */\n private tripStops: Array<{lat: number; lng: number}> = []\n private tripMode: string = \"driving\"\n\n private constructor() {}\n\n public static getInstance(): NavigationService {\n if (!NavigationService.instance) {\n NavigationService.instance = new NavigationService()\n }\n return NavigationService.instance\n }\n\n public getState(): NavState {\n return this.state\n }\n\n public addListener(listener: NavListener): () => void {\n this.listeners.add(listener)\n if (this.subs.length === 0) {\n this.attachNativeSubs()\n }\n return () => {\n this.listeners.delete(listener)\n if (this.noListeners()) {\n this.detachNativeSubs()\n }\n }\n }\n\n /**\n * Subscribe to the Mapbox Nav SDK's road-snapped location stream. Only\n * fires while a nav session is active. Returns an unsubscribe fn.\n */\n public addLocationListener(listener: NavLocationListener): () => void {\n this.locationListeners.add(listener)\n if (this.subs.length === 0) {\n this.attachNativeSubs()\n }\n return () => {\n this.locationListeners.delete(listener)\n if (this.noListeners()) {\n this.detachNativeSubs()\n }\n }\n }\n\n /**\n * Subscribe to the active route's polyline. Fires once per route build\n * (initial + after every reroute). Late subscribers get the current\n * route replayed on subscribe so the UI can render immediately.\n */\n public addRouteListener(listener: NavRouteListener): () => void {\n this.routeListeners.add(listener)\n if (this.subs.length === 0) {\n this.attachNativeSubs()\n }\n if (this.lastRoute) {\n try {\n listener(this.lastRoute)\n } catch (err) {\n console.error(`${LOG_TAG}: route listener threw on replay`, err)\n }\n }\n return () => {\n this.routeListeners.delete(listener)\n if (this.noListeners()) {\n this.detachNativeSubs()\n }\n }\n }\n\n private noListeners(): boolean {\n return this.listeners.size === 0 && this.locationListeners.size === 0 && this.routeListeners.size === 0\n }\n\n public async start(\n coords: {lat: number; lng: number},\n options?: {\n simulate?: boolean\n speedMultiplier?: number\n stops?: Array<{lat: number; lng: number}>\n mode?: string\n avoid?: {highways?: boolean; tolls?: boolean; ferries?: boolean}\n missedTurnRerouteMeters?: number\n },\n ): Promise<{ok: boolean; error?: string}> {\n console.log(\n `${LOG_TAG}: start ${coords.lat},${coords.lng} sim=${options?.simulate ?? false} speed=${options?.speedMultiplier ?? 5}`,\n )\n if (this.subs.length === 0) {\n // Listeners may attach after start(); make sure native subs exist\n // so we don't drop early events.\n this.attachNativeSubs()\n }\n // Resolve the token for the native SDK: user key first, else the public\n // render token served by Glassly Cloud. The binary bakes no key, so with\n // no resolvable token the trip must NOT start — the native SDK would\n // otherwise fail opaquely mid-boot. Cloud disabled + no user key lands\n // here by design. Pushed per-start rather than on settings change so it\n // can't race native boot.\n const mapboxRenderToken = await resolveMapboxRenderToken()\n if (!mapboxRenderToken) {\n const error =\n \"No Mapbox token available — add your key in Settings > API Keys\" +\n \" (required while Glassly Cloud is disabled or unreachable)\"\n console.warn(`${LOG_TAG}: start blocked — ${error}`)\n return {ok: false, error}\n }\n try {\n await CrustModule.setMapboxAccessToken(mapboxRenderToken)\n } catch (err) {\n // Native build predating setMapboxAccessToken — no token reaches the\n // SDK (nothing is baked), so fail the start rather than limp into an\n // opaque native error.\n console.warn(`${LOG_TAG}: setMapboxAccessToken unavailable`, err)\n return {ok: false, error: \"This build cannot receive a Mapbox token (update the app)\"}\n }\n const result = await CrustModule.startNavigation(coords.lat, coords.lng, {\n simulate: options?.simulate ?? false,\n speedMultiplier: options?.speedMultiplier ?? 5,\n stops: options?.stops,\n mode: options?.mode ?? \"driving\",\n avoid: options?.avoid,\n missedTurnRerouteMeters: options?.missedTurnRerouteMeters,\n })\n if (!result.ok) {\n console.warn(`${LOG_TAG}: start failed — ${result.error}`)\n this.state = \"idle\"\n this.tripStops = []\n this.tripMode = \"driving\"\n } else {\n this.state = \"navigating\"\n this.tripStops = options?.stops ?? [{lat: coords.lat, lng: coords.lng}]\n this.tripMode = options?.mode ?? \"driving\"\n }\n return result\n }\n\n /**\n * Snapshot of the active trip for `navigation.getState()`. Returns null\n * when no trip is running. The snapshot is built from in-memory state\n * fed by the existing native event stream — no extra IPC.\n */\n public getSnapshot(): NavTripSnapshot | null {\n if (this.state === \"idle\") return null\n const m = this.lastManeuver\n return {\n active: this.state !== \"arrived\",\n mode: this.tripMode,\n stops: this.tripStops.length > 0 ? this.tripStops : undefined,\n // Single-destination trips: index is always 0 (final stop). The Nav\n // SDK manages waypoint progression internally, so for now we report 0.\n currentStopIndex: 0,\n route: this.lastRoute ?? undefined,\n maneuver: m ?? undefined,\n distanceToDestinationMeters: m?.distanceToDestinationMeters,\n timeToDestinationSeconds: m?.timeToDestinationSeconds,\n currentSpeedMps: m?.currentSpeedMps,\n speedLimitMps: m?.speedLimitMps,\n }\n }\n\n public async stop(): Promise<{ok: boolean; error?: string}> {\n console.log(`${LOG_TAG}: stop`)\n const result = await CrustModule.stopNavigation()\n this.state = \"idle\"\n this.lastRoute = null\n this.lastManeuver = null\n this.tripStops = []\n this.tripMode = \"driving\"\n return result\n }\n\n /**\n * Request navigation permission. Under Mapbox there is no T&C dialog —\n * this resolves immediately with `accepted: true` — but it's still safe\n * (and intended) to call eagerly on mount.\n */\n public async requestPermission(): Promise<{ok: boolean; accepted: boolean; error?: string}> {\n console.log(`${LOG_TAG}: requestPermission`)\n return await CrustModule.requestNavigationPermission()\n }\n\n /**\n * Dev-only: nudge the simulator off-route to trigger an actual reroute\n * from the Nav SDK. Useful for verifying the rerouting pipeline (UI\n * flips to \"Rebuilding route…\", route polyline updates, glasses display\n * mirrors the new path). No-op on iOS or with real GPS fixes.\n */\n public async simulateDeviation(offsetMeters: number = 20): Promise<{ok: boolean; error?: string}> {\n console.log(`${LOG_TAG}: simulateDeviation(${offsetMeters}m)`)\n return await CrustModule.simulateDeviation(offsetMeters)\n }\n\n /**\n * Dev toggle: lock simulated locations onto the wrong sidewalk\n * (perpendicular-right of the route bearing by ~8m). Used to verify\n * the SDK's along-path pivot trigger fires even when the user never\n * comes within the 7m radius of a pivot point. Android-only today; iOS\n * is a no-op stub.\n */\n public async setWrongSidewalkOffset(enabled: boolean): Promise<{ok: boolean; error?: string}> {\n console.log(`${LOG_TAG}: setWrongSidewalkOffset(${enabled})`)\n return await CrustModule.setWrongSidewalkOffset(enabled)\n }\n\n /**\n * Dev toggle: take over from the Google simulator and walk the user\n * along a modified polyline that skips crossing micro-steps. Lets us\n * reproduce the wrong-sidewalk-then-missed-the-turn scenario for\n * pivot trigger testing. Android-only today; iOS is a no-op stub.\n */\n public async setSkipCrossings(enabled: boolean): Promise<{ok: boolean; error?: string}> {\n console.log(`${LOG_TAG}: setSkipCrossings(${enabled})`)\n return await CrustModule.setSkipCrossings(enabled)\n }\n\n /**\n * Compute one or more routes without starting a trip.\n *\n * Reached from the miniapp bridge (NavigationHandlers.handleComputeRoute)\n * when the user has saved their own Mapbox key in Settings > API Keys —\n * that key exists so navigation works without the cloud. Without a user\n * key the bridge uses the v2 cloud maps service, which holds a provider\n * token server-side and caches results. Implemented by\n * calling Mapbox's Directions API (REST) so we don't disturb the active\n * Navigator. Returns `{ok: false}` plus an error string when the engine\n * can't produce a route — mirrors the SDK's ComputeRouteResult shape so\n * the host can pass it back to miniapps unchanged.\n */\n public async computeRoute(payload: Record<string, unknown>): Promise<{\n ok: boolean\n error?: string\n routes?: Array<{\n points: Array<{lat: number; lng: number}>\n totalDistanceMeters: number\n totalDurationSeconds: number\n summary?: string\n }>\n }> {\n return computeRouteViaRoutesApi(payload)\n }\n\n /**\n * Reverse-geocode a coordinate into a short road/route name (plus the full\n * formatted `address` for dropped-pin / POI labels).\n *\n * Reached from the miniapp bridge when the user has saved their own Mapbox\n * key; otherwise the bridge uses the v2 cloud maps service. See\n * {@link computeRoute} for the same local-first branch.\n *\n * Implemented via Mapbox's Geocoding REST API. Backs the SDK pivot engine's\n * last-resort fallback when a Routes-API instruction didn't carry a parseable\n * road. Returns `{ok: true, road: null}` when the coordinate is genuinely\n * off-grid (mid-park, water) — that's a successful query with no road\n * component, distinct from a failure.\n */\n public async reverseGeocodeRoad(coord: {lat: number; lng: number}): Promise<{\n ok: boolean\n road?: string | null\n address?: string | null\n error?: string\n }> {\n return reverseGeocodeRoadViaGeocodingApi(coord)\n }\n\n /** True when a phone-side DIRECT Mapbox call can be made (user key saved). */\n public hasMapboxToken(): boolean {\n return !!resolveMapboxAccessToken()\n }\n\n /** True when the user saved their own Mapbox key in Settings > API Keys. */\n public hasUserMapboxKey(): boolean {\n return !!userMapboxApiKey()\n }\n\n /**\n * Type-ahead place search on-device with the user's own Mapbox key.\n * Preferred over the cloud maps service whenever that key is set — see\n * {@link placeAutocompleteViaSearchBox}.\n */\n public async placeAutocomplete(\n query: string,\n near: {lat: number; lng: number} | undefined,\n sessionToken: string,\n ): Promise<{\n ok: boolean\n suggestions?: Array<{placeId: string; mainText: string; secondaryText: string; distanceMeters?: number}>\n error?: string\n }> {\n return placeAutocompleteViaSearchBox(query, near, sessionToken)\n }\n\n /** Resolve a suggestion to coordinates on-device. Pairs with {@link placeAutocomplete}. */\n public async placeDetails(\n placeId: string,\n sessionToken: string,\n ): Promise<{\n ok: boolean\n place?: {placeId: string; name: string; address: string; lat: number; lng: number}\n error?: string\n }> {\n return placeDetailsViaSearchBox(placeId, sessionToken)\n }\n\n private attachNativeSubs(): void {\n console.log(`${LOG_TAG}: attachNativeSubs() — listeners=${this.listeners.size}`)\n this.subs.push(\n CrustModule.addListener(\"onNavManeuver\", (data) => {\n this.state = \"navigating\"\n const event: NavManeuver = {kind: \"maneuver\", ...data}\n this.lastManeuver = event\n this.fanout(event)\n }),\n CrustModule.addListener(\"onNavRerouting\", () => {\n console.log(`${LOG_TAG}: ← onNavRerouting`)\n this.state = \"rerouting\"\n this.fanout({kind: \"rerouting\"})\n }),\n CrustModule.addListener(\"onNavArrived\", () => {\n console.log(`${LOG_TAG}: ← onNavArrived`)\n this.state = \"arrived\"\n this.lastManeuver = null\n this.fanout({kind: \"arrived\"})\n }),\n CrustModule.addListener(\"onNavError\", (data) => {\n console.log(`${LOG_TAG}: ← onNavError`, data?.message)\n this.fanout({kind: \"error\", message: data.message})\n }),\n CrustModule.addListener(\"onNavLocation\", (data) => {\n const loc: NavLocation = {\n lat: data.lat,\n lng: data.lng,\n accuracy: data.accuracy ?? null,\n timestamp: data.timestamp,\n }\n this.locationListeners.forEach((l) => {\n try {\n l(loc)\n } catch (err) {\n console.error(`${LOG_TAG}: location listener threw`, err)\n }\n })\n }),\n CrustModule.addListener(\"onNavRoute\", (data) => {\n const route: NavRoute = {\n points: data.points ?? [],\n steps: data.steps?.map((step) => ({\n ...step,\n road: step.road ?? null,\n })),\n }\n this.lastRoute = route\n console.log(`${LOG_TAG}: ← onNavRoute (${route.points.length} points, steps=${route.steps?.length ?? \"null\"})`)\n this.routeListeners.forEach((l) => {\n try {\n l(route)\n } catch (err) {\n console.error(`${LOG_TAG}: route listener threw`, err)\n }\n })\n }),\n CrustModule.addListener(\"onNavOffRoute\", (data) => {\n console.log(`${LOG_TAG}: ← onNavOffRoute`, data?.offRouteDistanceMeters)\n this.fanout({kind: \"off_route\", offRouteDistanceMeters: data?.offRouteDistanceMeters ?? 0})\n }),\n )\n }\n\n private detachNativeSubs(): void {\n this.subs.forEach((s) => s.remove())\n this.subs = []\n }\n\n private fanout(update: NavUpdate): void {\n this.listeners.forEach((l) => {\n try {\n l(update)\n } catch (err) {\n console.error(`${LOG_TAG}: listener threw`, err)\n }\n })\n }\n}\n\nconst navigationService = NavigationService.getInstance()\nexport default navigationService\n\n// ---------------------------------------------------------------------------\n// Routes API (REST)\n// ---------------------------------------------------------------------------\n\n// Routes + Geocoding go DIRECT to Mapbox from the phone process ONLY when the\n// user saved their own key (Settings > API Keys) — \"use my account\". Without\n// one, callers (NavigationHandlers) route these operations through the v2\n// cloud maps proxy instead; the binary ships no baked Mapbox key.\nconst MAPBOX_DIRECTIONS_BASE = \"https://api.mapbox.com/directions/v5/mapbox\"\nconst MAPBOX_GEOCODE_REVERSE = \"https://api.mapbox.com/search/geocode/v6/reverse\"\nconst MAPBOX_SEARCHBOX_SUGGEST = \"https://api.mapbox.com/search/searchbox/v1/suggest\"\n\n/** Place search sits in front of a voice command; a stalled call must fail over, not hang. */\nconst PLACE_SEARCH_TIMEOUT_MS = 6_000\n\nasync function fetchWithTimeout(url: string, timeoutMs: number): Promise<Response> {\n const controller = new AbortController()\n const timer = BgTimer.setTimeout(() => controller.abort(), timeoutMs)\n try {\n return await fetch(url, {method: \"GET\", signal: controller.signal})\n } finally {\n BgTimer.clearTimeout(timer)\n }\n}\nconst MAPBOX_SEARCHBOX_RETRIEVE = \"https://api.mapbox.com/search/searchbox/v1/retrieve\"\n\n/**\n * The Mapbox token for phone-side REST calls: the user's key\n * (Settings > Keys) or nothing — empty means \"use the cloud maps proxy\".\n */\nfunction mapboxToken(): string {\n return resolveMapboxAccessToken()\n}\n\n/**\n * Phone-side helper: hit the Mapbox Directions API directly with the user's own\n * key (Settings > API Keys). Preferred over the v2 cloud maps service whenever\n * that key is set, so routing works without the cloud. Lives here\n * (not in Kotlin) so it's platform-independent across the JS bridge.\n * Returns the SDK-shaped result with primary + alternates.\n *\n * Mapbox Directions differs from Google Routes in shape: numeric\n * `distance`/`duration`, `polyline6` geometry per-route AND per-step, and\n * `maneuver = {location:[lng,lat], type, modifier, instruction}`. We\n * synthesize the SDK's `ComputedRouteStep` (lat/lng start, endLat/endLng\n * = next step's start) from the ordered step list.\n */\nasync function computeRouteViaRoutesApi(payload: Record<string, unknown>): Promise<{\n ok: boolean\n error?: string\n routes?: Array<{\n points: Array<{lat: number; lng: number}>\n totalDistanceMeters: number\n totalDurationSeconds: number\n summary?: string\n steps?: Array<{\n lat: number\n lng: number\n endLat: number\n endLng: number\n distanceMeters: number\n maneuver?: string\n instruction?: string\n road?: string | null\n }>\n }>\n}> {\n const origin = payload.origin as {lat?: unknown; lng?: unknown} | undefined\n const stopsRaw = payload.stops as Array<{lat?: unknown; lng?: unknown}> | undefined\n const mode = (typeof payload.mode === \"string\" ? payload.mode : \"driving\").toLowerCase()\n const alt = Number(payload.alternatives)\n const alternatives = Number.isFinite(alt) && alt > 0 ? alt : 1\n const avoid = (payload.avoid as Record<string, unknown> | undefined) ?? {}\n\n const oLat = Number(origin?.lat)\n const oLng = Number(origin?.lng)\n if (!Number.isFinite(oLat) || !Number.isFinite(oLng)) {\n return {ok: false, error: \"computeRoute: origin.lat/lng required\"}\n }\n const stops = (Array.isArray(stopsRaw) ? stopsRaw : [])\n .map((s) => ({lat: Number(s?.lat), lng: Number(s?.lng)}))\n .filter((s) => Number.isFinite(s.lat) && Number.isFinite(s.lng))\n if (stops.length === 0) {\n return {ok: false, error: \"computeRoute: at least one stop required\"}\n }\n\n const token = mapboxToken()\n if (!token) return {ok: false, error: \"computeRoute: no Mapbox key saved (add yours in Settings > API Keys)\"}\n\n // Mapbox path is a semicolon-joined `lng,lat` list: origin then each stop.\n const coords = [`${oLng},${oLat}`, ...stops.map((s) => `${s.lng},${s.lat}`)].join(\";\")\n const exclude = mapboxExclude(avoid)\n const params = new URLSearchParams({\n alternatives: String(alternatives > 1),\n geometries: \"polyline6\",\n overview: \"full\",\n steps: \"true\",\n banner_instructions: \"true\",\n voice_instructions: \"false\",\n access_token: token,\n })\n if (exclude) params.set(\"exclude\", exclude)\n const url = `${MAPBOX_DIRECTIONS_BASE}/${mapboxProfile(mode)}/${coords}?${params.toString()}`\n\n try {\n const res = await fetch(url, {method: \"GET\"})\n if (!res.ok) {\n return {ok: false, error: `Directions API ${res.status}`}\n }\n const json = (await res.json()) as {\n code?: string\n message?: string\n routes?: Array<{\n geometry?: string\n distance?: number\n duration?: string | number\n weight_name?: string\n legs?: Array<{\n summary?: string\n steps?: Array<{\n geometry?: string\n name?: string\n distance?: number\n maneuver?: {location?: [number, number]; type?: string; modifier?: string; instruction?: string}\n }>\n }>\n }>\n }\n if (json.code && json.code !== \"Ok\") {\n return {ok: false, error: json.message ?? `Directions code ${json.code}`}\n }\n // Resolve `road` for every step whose Mapbox `name` was blank (slip\n // lanes, unnamed paths, arrival legs) via reverse-geocode. Per-route\n // and per-alternate resolution fire concurrently.\n const routes = await Promise.all(\n (json.routes ?? []).slice(0, alternatives).map(async (r) => {\n const legs = r.legs ?? []\n const flatSteps = legs.flatMap((leg) => leg.steps ?? [])\n const rawSteps = flatSteps.map((s, i) => {\n const here = s.maneuver?.location // [lng, lat]\n const next = flatSteps[i + 1]?.maneuver?.location\n const lat = here?.[1] ?? Number.NaN\n const lng = here?.[0] ?? Number.NaN\n return {\n lat,\n lng,\n // End of step i == start of step i+1; final step ends at itself.\n endLat: next?.[1] ?? lat,\n endLng: next?.[0] ?? lng,\n distanceMeters: Math.round(s.distance ?? 0),\n maneuver: mapboxManeuverToKind(s.maneuver?.type, s.maneuver?.modifier),\n instruction: s.maneuver?.instruction,\n // Mapbox gives the road name inline as `step.name`; prefer it\n // over geocoding. Blank names fall through to resolveStepRoads.\n road: s.name && s.name.trim().length > 0 ? s.name.trim() : undefined,\n }\n })\n const steps = await resolveStepRoads(rawSteps, reverseGeocodeRoadViaGeocodingApi)\n return {\n points: decodePolyline(r.geometry ?? \"\", 6),\n totalDistanceMeters: Math.round(r.distance ?? 0),\n totalDurationSeconds: parseDurationSeconds(r.duration ?? 0),\n summary: legs[0]?.summary,\n steps: steps.length > 0 ? steps : undefined,\n }\n }),\n )\n if (routes.length === 0) return {ok: false, error: \"no routes returned\"}\n return {ok: true, routes}\n } catch (err) {\n return {ok: false, error: err instanceof Error ? err.message : \"computeRoute failed\"}\n }\n}\n\n/** SDK-agnostic mode → Mapbox Directions profile. two_wheeler → driving. */\nfunction mapboxProfile(mode: string): string {\n switch (mode) {\n case \"walking\":\n return \"walking\"\n case \"cycling\":\n return \"cycling\"\n case \"two_wheeler\":\n return \"driving\"\n default:\n return \"driving-traffic\"\n }\n}\n\n/** Avoid flags → Mapbox `exclude` param. Null when nothing to exclude. */\nfunction mapboxExclude(avoid: Record<string, unknown>): string | null {\n const ex: string[] = []\n if (avoid.tolls === true) ex.push(\"toll\")\n if (avoid.ferries === true) ex.push(\"ferry\")\n if (avoid.highways === true) ex.push(\"motorway\")\n return ex.length > 0 ? ex.join(\",\") : null\n}\n\n/**\n * Map Mapbox `maneuver.type` + `modifier` to the SDK's ManeuverKind\n * vocabulary — the JS-side mirror of NavigationManager.kt's mapManeuver\n * (issues/mapbox-navigation-migration.md §7). Kept here so the\n * computeRoute preview path labels turns the same way the live trip does.\n */\nfunction mapboxManeuverToKind(type?: string, modifier?: string): string | undefined {\n switch (type) {\n case \"depart\":\n return \"DEPART\"\n case \"arrive\":\n return \"ARRIVE\"\n case \"new name\":\n return \"NAME_CHANGE\"\n case \"continue\":\n case \"merge\":\n return \"CONTINUE\"\n case \"notification\":\n return \"STRAIGHT\"\n default:\n break\n }\n switch (modifier) {\n case \"uturn\":\n return \"U_TURN\"\n case \"sharp left\":\n return \"SHARP_LEFT\"\n case \"left\":\n return \"TURN_LEFT\"\n case \"slight left\":\n return \"SLIGHT_LEFT\"\n case \"straight\":\n return \"STRAIGHT\"\n case \"slight right\":\n return \"SLIGHT_RIGHT\"\n case \"right\":\n return \"TURN_RIGHT\"\n case \"sharp right\":\n return \"SHARP_RIGHT\"\n default:\n return type ? \"STRAIGHT\" : undefined\n }\n}\n\n/**\n * Reverse-geocode a coordinate via the Mapbox Geocoding v6 API directly, using\n * the user's own key (Settings > API Keys). Preferred over the v2 cloud maps\n * service whenever that key is set, so pin labels work without the cloud.\n *\n * Returns the road/street name (e.g. \"Octavia Blvd\") plus the full formatted\n * `address` for dropped-pin / POI labels. When no street is\n * present — the coordinate is genuinely off-grid (water, park interior) —\n * resolves with `{ok: true, road: null}`. Network failures and missing\n * token resolve with `{ok: false, error}`.\n *\n * Mapbox v6 returns a GeoJSON FeatureCollection; the street name lives at\n * `features[0].properties.context.street.name`. We also accept a feature\n * whose own `feature_type` is `street` (its `name` is the road). We prefer\n * the most-specific feature (the first), matching how the Google-era code\n * took the first `route` component.\n */\nasync function reverseGeocodeRoadViaGeocodingApi(coord: {lat: number; lng: number}): Promise<{\n ok: boolean\n road?: string | null\n address?: string | null\n error?: string\n}> {\n if (!Number.isFinite(coord.lat) || !Number.isFinite(coord.lng)) {\n return {ok: false, error: \"reverseGeocode: invalid coord\"}\n }\n const token = mapboxToken()\n if (!token)\n return {\n ok: false,\n error: \"reverseGeocode: no Mapbox key saved (add yours in Settings > API Keys)\",\n }\n const params = new URLSearchParams({\n longitude: String(coord.lng),\n latitude: String(coord.lat),\n // Bias toward address/street features so the street context is present.\n types: \"address,street\",\n limit: \"1\",\n access_token: token,\n })\n try {\n const res = await fetch(`${MAPBOX_GEOCODE_REVERSE}?${params.toString()}`, {method: \"GET\"})\n if (!res.ok) return {ok: false, error: `Geocoding API ${res.status}`}\n const json = (await res.json()) as {\n features?: Array<{\n properties?: {\n feature_type?: string\n name?: string\n full_address?: string\n place_formatted?: string\n context?: {street?: {name?: string}}\n }\n }>\n }\n // The full formatted address for dropped-pin / POI labels, taken from the\n // most-specific feature. Same precedence as the cloud provider so both\n // paths label a pin identically.\n const first = json.features?.[0]?.properties\n const address = (first?.full_address ?? first?.name ?? first?.place_formatted ?? \"\").trim() || null\n\n for (const feature of json.features ?? []) {\n const props = feature.properties\n // A street-type feature's own name is the road; otherwise read the\n // street from context.\n const fromStreetType = props?.feature_type === \"street\" ? props?.name : undefined\n const name = (fromStreetType ?? props?.context?.street?.name ?? \"\").trim()\n if (name) return {ok: true, road: name, address}\n }\n return {ok: true, road: null, address}\n } catch (err) {\n return {ok: false, error: err instanceof Error ? err.message : \"reverseGeocode failed\"}\n }\n}\n\n/**\n * Type-ahead place search straight from the device via Mapbox Search Box,\n * using the user's own key (Settings > API Keys). This is the offline-from-\n * the-cloud path: with a key saved, place search works with no runtime\n * involvement at all.\n *\n * Field extraction mirrors the cloud provider so both paths return identical\n * suggestions: only entries carrying a `mapbox_id` survive (without one there\n * is nothing to retrieve later), and the secondary line prefers\n * `place_formatted` over `full_address`.\n *\n * An empty query short-circuits to no suggestions — Search Box answers 422 for\n * a blank `q`. A missing token resolves `{ok: false}` so the caller can fall\n * back to the cloud.\n */\nasync function placeAutocompleteViaSearchBox(\n query: string,\n near: {lat: number; lng: number} | undefined,\n sessionToken: string,\n): Promise<{\n ok: boolean\n suggestions?: Array<{placeId: string; mainText: string; secondaryText: string; distanceMeters?: number}>\n error?: string\n}> {\n if (!query.trim()) return {ok: true, suggestions: []}\n const token = mapboxToken()\n if (!token) {\n return {\n ok: false,\n error: \"placeAutocomplete: no Mapbox key saved (add yours in Settings > API Keys)\",\n }\n }\n const params = new URLSearchParams({\n q: query,\n access_token: token,\n session_token: sessionToken,\n // POIs + addresses + places — the things a user navigates to.\n types: \"poi,address,place,street\",\n limit: \"10\",\n })\n // Mapbox wants lng,lat for proximity bias; `origin` adds per-suggestion distance.\n if (near) {\n params.set(\"proximity\", `${near.lng},${near.lat}`)\n params.set(\"origin\", `${near.lng},${near.lat}`)\n }\n\n try {\n const res = await fetchWithTimeout(`${MAPBOX_SEARCHBOX_SUGGEST}?${params.toString()}`, PLACE_SEARCH_TIMEOUT_MS)\n if (!res.ok) return {ok: false, error: `Search Box suggest ${res.status}`}\n const json = (await res.json()) as {\n suggestions?: Array<{\n mapbox_id?: string\n name?: string\n place_formatted?: string\n full_address?: string\n distance?: number\n }>\n }\n const suggestions = (json.suggestions ?? [])\n .filter((s): s is {mapbox_id: string} & typeof s => !!s.mapbox_id)\n .map((s) => ({\n placeId: s.mapbox_id,\n mainText: s.name ?? \"\",\n secondaryText: s.place_formatted ?? s.full_address ?? \"\",\n ...(typeof s.distance === \"number\" ? {distanceMeters: s.distance} : {}),\n }))\n return {ok: true, suggestions}\n } catch (err) {\n return {ok: false, error: err instanceof Error ? err.message : \"placeAutocomplete failed\"}\n }\n}\n\n/**\n * Resolve a Search Box suggestion to a full place with coordinates, using the\n * user's own key. Pairs with {@link placeAutocompleteViaSearchBox} — the same\n * `sessionToken` must thread both calls so Mapbox bills the keystrokes plus\n * this retrieve as one search session.\n *\n * Retrieve answers a GeoJSON FeatureCollection; coordinates live at\n * `features[0].geometry.coordinates` as [lng, lat].\n */\nasync function placeDetailsViaSearchBox(\n placeId: string,\n sessionToken: string,\n): Promise<{\n ok: boolean\n place?: {placeId: string; name: string; address: string; lat: number; lng: number}\n error?: string\n}> {\n const token = mapboxToken()\n if (!token) {\n return {\n ok: false,\n error: \"placeDetails: no Mapbox key saved (add yours in Settings > API Keys)\",\n }\n }\n const params = new URLSearchParams({access_token: token, session_token: sessionToken})\n try {\n const res = await fetchWithTimeout(\n `${MAPBOX_SEARCHBOX_RETRIEVE}/${encodeURIComponent(placeId)}?${params.toString()}`,\n PLACE_SEARCH_TIMEOUT_MS,\n )\n if (!res.ok) return {ok: false, error: `Search Box retrieve ${res.status}`}\n const json = (await res.json()) as {\n features?: Array<{\n geometry?: {coordinates?: [number, number]}\n properties?: {\n name?: string\n full_address?: string\n place_formatted?: string\n }\n }>\n }\n const feature = json.features?.[0]\n const coords = feature?.geometry?.coordinates\n if (!coords || coords.length < 2 || !Number.isFinite(coords[0]) || !Number.isFinite(coords[1])) {\n return {ok: false, error: \"placeDetails: no coordinates for place\"}\n }\n const props = feature?.properties\n return {\n ok: true,\n place: {\n placeId,\n name: props?.name ?? \"\",\n address: props?.full_address ?? props?.place_formatted ?? \"\",\n lng: coords[0],\n lat: coords[1],\n },\n }\n } catch (err) {\n return {ok: false, error: err instanceof Error ? err.message : \"placeDetails failed\"}\n }\n}\n"]}
1
+ {"version":3,"file":"NavigationService.js","sourceRoot":"","sources":["../../src/services/NavigationService.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * NavigationService\n *\n * Thin singleton wrapper around the native Mapbox Navigation SDK exposed\n * by the `crust` Expo module.\n *\n * Mini apps will eventually subscribe through the mini app SDK, which\n * routes via LocalMiniappRuntime and ultimately calls into here. For now,\n * this is also called directly by the developer-settings test button.\n *\n * Works on both Android and iOS via the native Mapbox Navigation SDK.\n */\n\nimport CrustModule from \"@glassly/crust\"\n\nimport {resolveMapboxAccessToken, resolveMapboxRenderToken, userMapboxApiKey} from \"./MapboxTokenService\"\nimport {decodePolyline, parseDurationSeconds} from \"./navigation/routesApiCodec\"\nimport {resolveStepRoads} from \"./navigation/roadNameResolver\"\nimport {BgTimer} from \"../utils/timers\"\n\nconst LOG_TAG = \"NAV_SERVICE\"\n\nexport type NavManeuver = {\n kind: \"maneuver\"\n /**\n * Categorical type of the upcoming maneuver. One of: STRAIGHT,\n * SLIGHT_LEFT, SLIGHT_RIGHT, TURN_LEFT, TURN_RIGHT, SHARP_LEFT,\n * SHARP_RIGHT, U_TURN, ARRIVE.\n */\n maneuverType: string\n distanceMeters: number\n /** Road the user is currently on. Null if the SDK didn't supply one. */\n fromRoad?: string | null\n /** Road the user will be on after the maneuver. Null if the SDK didn't supply one. */\n toRoad?: string | null\n distanceToDestinationMeters?: number\n timeToDestinationSeconds?: number\n currentSpeedMps?: number | null\n speedLimitMps?: number | null\n routeHeadingDeg?: number | null\n}\n\nexport type NavOffRoute = {\n kind: \"off_route\"\n offRouteDistanceMeters: number\n}\n\nexport type NavRerouting = {kind: \"rerouting\"}\nexport type NavArrived = {kind: \"arrived\"}\nexport type NavError = {kind: \"error\"; message: string}\n\nexport type NavUpdate = NavManeuver | NavOffRoute | NavRerouting | NavArrived | NavError\n\nexport type NavListener = (update: NavUpdate) => void\n\nexport type NavLocation = {\n lat: number\n lng: number\n accuracy: number | null\n timestamp: number\n}\nexport type NavLocationListener = (loc: NavLocation) => void\n\nexport type NavRouteStep = {\n lat: number\n lng: number\n routeIndex: number\n road: string | null\n maneuver: string\n distanceMeters: number\n}\nexport type NavRoute = {\n points: Array<{lat: number; lng: number}>\n steps?: NavRouteStep[]\n}\nexport type NavRouteListener = (route: NavRoute) => void\n\nexport type NavState = \"idle\" | \"navigating\" | \"rerouting\" | \"arrived\"\n\n/**\n * Snapshot of the active trip — fed to miniapps that open mid-trip via\n * `navigation.getState()`. Mirrors the SDK's NavState shape closely; the\n * runtime keeps it strictly in sync as nav events arrive.\n */\nexport type NavTripSnapshot = {\n active: boolean\n mode?: string\n stops?: Array<{lat: number; lng: number}>\n currentStopIndex?: number\n route?: NavRoute\n maneuver?: NavManeuver\n distanceToDestinationMeters?: number\n timeToDestinationSeconds?: number\n currentSpeedMps?: number | null\n speedLimitMps?: number | null\n}\n\nclass NavigationService {\n private static instance: NavigationService | null = null\n private listeners = new Set<NavListener>()\n private locationListeners = new Set<NavLocationListener>()\n private routeListeners = new Set<NavRouteListener>()\n private subs: Array<{remove: () => void}> = []\n private state: NavState = \"idle\"\n /** Last emitted route — replayed to late subscribers so they get the\n * current geometry immediately. */\n private lastRoute: NavRoute | null = null\n /** Last maneuver event observed — used to hydrate getState() on mid-trip mount. */\n private lastManeuver: NavManeuver | null = null\n /** Trip configuration captured at start(), surfaced via getState(). */\n private tripStops: Array<{lat: number; lng: number}> = []\n private tripMode: string = \"walking\"\n\n private constructor() {}\n\n public static getInstance(): NavigationService {\n if (!NavigationService.instance) {\n NavigationService.instance = new NavigationService()\n }\n return NavigationService.instance\n }\n\n public getState(): NavState {\n return this.state\n }\n\n public addListener(listener: NavListener): () => void {\n this.listeners.add(listener)\n if (this.subs.length === 0) {\n this.attachNativeSubs()\n }\n return () => {\n this.listeners.delete(listener)\n if (this.noListeners()) {\n this.detachNativeSubs()\n }\n }\n }\n\n /**\n * Subscribe to the Mapbox Nav SDK's road-snapped location stream. Only\n * fires while a nav session is active. Returns an unsubscribe fn.\n */\n public addLocationListener(listener: NavLocationListener): () => void {\n this.locationListeners.add(listener)\n if (this.subs.length === 0) {\n this.attachNativeSubs()\n }\n return () => {\n this.locationListeners.delete(listener)\n if (this.noListeners()) {\n this.detachNativeSubs()\n }\n }\n }\n\n /**\n * Subscribe to the active route's polyline. Fires once per route build\n * (initial + after every reroute). Late subscribers get the current\n * route replayed on subscribe so the UI can render immediately.\n */\n public addRouteListener(listener: NavRouteListener): () => void {\n this.routeListeners.add(listener)\n if (this.subs.length === 0) {\n this.attachNativeSubs()\n }\n if (this.lastRoute) {\n try {\n listener(this.lastRoute)\n } catch (err) {\n console.error(`${LOG_TAG}: route listener threw on replay`, err)\n }\n }\n return () => {\n this.routeListeners.delete(listener)\n if (this.noListeners()) {\n this.detachNativeSubs()\n }\n }\n }\n\n private noListeners(): boolean {\n return this.listeners.size === 0 && this.locationListeners.size === 0 && this.routeListeners.size === 0\n }\n\n public async start(\n coords: {lat: number; lng: number},\n options?: {\n simulate?: boolean\n speedMultiplier?: number\n stops?: Array<{lat: number; lng: number}>\n mode?: string\n avoid?: {highways?: boolean; tolls?: boolean; ferries?: boolean}\n missedTurnRerouteMeters?: number\n },\n ): Promise<{ok: boolean; error?: string}> {\n console.log(\n `${LOG_TAG}: start ${coords.lat},${coords.lng} sim=${options?.simulate ?? false} speed=${options?.speedMultiplier ?? 5}`,\n )\n if (this.subs.length === 0) {\n // Listeners may attach after start(); make sure native subs exist\n // so we don't drop early events.\n this.attachNativeSubs()\n }\n // Resolve the token for the native SDK: user key first, else the public\n // render token served by Glassly Cloud. The binary bakes no key, so with\n // no resolvable token the trip must NOT start — the native SDK would\n // otherwise fail opaquely mid-boot. Cloud disabled + no user key lands\n // here by design. Pushed per-start rather than on settings change so it\n // can't race native boot.\n const mapboxRenderToken = await resolveMapboxRenderToken()\n if (!mapboxRenderToken) {\n const error =\n \"No Mapbox token available — add your key in Settings > API Keys\" +\n \" (required while Glassly Cloud is disabled or unreachable)\"\n console.warn(`${LOG_TAG}: start blocked — ${error}`)\n return {ok: false, error}\n }\n try {\n await CrustModule.setMapboxAccessToken(mapboxRenderToken)\n } catch (err) {\n // Native build predating setMapboxAccessToken — no token reaches the\n // SDK (nothing is baked), so fail the start rather than limp into an\n // opaque native error.\n console.warn(`${LOG_TAG}: setMapboxAccessToken unavailable`, err)\n return {ok: false, error: \"This build cannot receive a Mapbox token (update the app)\"}\n }\n const result = await CrustModule.startNavigation(coords.lat, coords.lng, {\n simulate: options?.simulate ?? false,\n speedMultiplier: options?.speedMultiplier ?? 5,\n stops: options?.stops,\n mode: options?.mode ?? \"walking\",\n avoid: options?.avoid,\n missedTurnRerouteMeters: options?.missedTurnRerouteMeters,\n })\n if (!result.ok) {\n console.warn(`${LOG_TAG}: start failed — ${result.error}`)\n this.state = \"idle\"\n this.tripStops = []\n this.tripMode = \"walking\"\n } else {\n this.state = \"navigating\"\n this.tripStops = options?.stops ?? [{lat: coords.lat, lng: coords.lng}]\n this.tripMode = options?.mode ?? \"walking\"\n }\n return result\n }\n\n /**\n * Snapshot of the active trip for `navigation.getState()`. Returns null\n * when no trip is running. The snapshot is built from in-memory state\n * fed by the existing native event stream — no extra IPC.\n */\n public getSnapshot(): NavTripSnapshot | null {\n if (this.state === \"idle\") return null\n const m = this.lastManeuver\n return {\n active: this.state !== \"arrived\",\n mode: this.tripMode,\n stops: this.tripStops.length > 0 ? this.tripStops : undefined,\n // Single-destination trips: index is always 0 (final stop). The Nav\n // SDK manages waypoint progression internally, so for now we report 0.\n currentStopIndex: 0,\n route: this.lastRoute ?? undefined,\n maneuver: m ?? undefined,\n distanceToDestinationMeters: m?.distanceToDestinationMeters,\n timeToDestinationSeconds: m?.timeToDestinationSeconds,\n currentSpeedMps: m?.currentSpeedMps,\n speedLimitMps: m?.speedLimitMps,\n }\n }\n\n public async stop(): Promise<{ok: boolean; error?: string}> {\n console.log(`${LOG_TAG}: stop`)\n const result = await CrustModule.stopNavigation()\n this.state = \"idle\"\n this.lastRoute = null\n this.lastManeuver = null\n this.tripStops = []\n this.tripMode = \"walking\"\n return result\n }\n\n /**\n * Request navigation permission. Under Mapbox there is no T&C dialog —\n * this resolves immediately with `accepted: true` — but it's still safe\n * (and intended) to call eagerly on mount.\n */\n public async requestPermission(): Promise<{ok: boolean; accepted: boolean; error?: string}> {\n console.log(`${LOG_TAG}: requestPermission`)\n return await CrustModule.requestNavigationPermission()\n }\n\n /**\n * Dev-only: nudge the simulator off-route to trigger an actual reroute\n * from the Nav SDK. Useful for verifying the rerouting pipeline (UI\n * flips to \"Rebuilding route…\", route polyline updates, glasses display\n * mirrors the new path). No-op on iOS or with real GPS fixes.\n */\n public async simulateDeviation(offsetMeters: number = 20): Promise<{ok: boolean; error?: string}> {\n console.log(`${LOG_TAG}: simulateDeviation(${offsetMeters}m)`)\n return await CrustModule.simulateDeviation(offsetMeters)\n }\n\n /**\n * Dev toggle: lock simulated locations onto the wrong sidewalk\n * (perpendicular-right of the route bearing by ~8m). Used to verify\n * the SDK's along-path pivot trigger fires even when the user never\n * comes within the 7m radius of a pivot point. Android-only today; iOS\n * is a no-op stub.\n */\n public async setWrongSidewalkOffset(enabled: boolean): Promise<{ok: boolean; error?: string}> {\n console.log(`${LOG_TAG}: setWrongSidewalkOffset(${enabled})`)\n return await CrustModule.setWrongSidewalkOffset(enabled)\n }\n\n /**\n * Dev toggle: take over from the Google simulator and walk the user\n * along a modified polyline that skips crossing micro-steps. Lets us\n * reproduce the wrong-sidewalk-then-missed-the-turn scenario for\n * pivot trigger testing. Android-only today; iOS is a no-op stub.\n */\n public async setSkipCrossings(enabled: boolean): Promise<{ok: boolean; error?: string}> {\n console.log(`${LOG_TAG}: setSkipCrossings(${enabled})`)\n return await CrustModule.setSkipCrossings(enabled)\n }\n\n /**\n * Compute one or more routes without starting a trip.\n *\n * Reached from the miniapp bridge (NavigationHandlers.handleComputeRoute)\n * when the user has saved their own Mapbox key in Settings > API Keys —\n * that key exists so navigation works without the cloud. Without a user\n * key the bridge uses the v2 cloud maps service, which holds a provider\n * token server-side and caches results. Implemented by\n * calling Mapbox's Directions API (REST) so we don't disturb the active\n * Navigator. Returns `{ok: false}` plus an error string when the engine\n * can't produce a route — mirrors the SDK's ComputeRouteResult shape so\n * the host can pass it back to miniapps unchanged.\n */\n public async computeRoute(payload: Record<string, unknown>): Promise<{\n ok: boolean\n error?: string\n routes?: Array<{\n points: Array<{lat: number; lng: number}>\n totalDistanceMeters: number\n totalDurationSeconds: number\n summary?: string\n }>\n }> {\n return computeRouteViaRoutesApi(payload)\n }\n\n /**\n * Reverse-geocode a coordinate into a short road/route name (plus the full\n * formatted `address` for dropped-pin / POI labels).\n *\n * Reached from the miniapp bridge when the user has saved their own Mapbox\n * key; otherwise the bridge uses the v2 cloud maps service. See\n * {@link computeRoute} for the same local-first branch.\n *\n * Implemented via Mapbox's Geocoding REST API. Backs the SDK pivot engine's\n * last-resort fallback when a Routes-API instruction didn't carry a parseable\n * road. Returns `{ok: true, road: null}` when the coordinate is genuinely\n * off-grid (mid-park, water) — that's a successful query with no road\n * component, distinct from a failure.\n */\n public async reverseGeocodeRoad(coord: {lat: number; lng: number}): Promise<{\n ok: boolean\n road?: string | null\n address?: string | null\n error?: string\n }> {\n return reverseGeocodeRoadViaGeocodingApi(coord)\n }\n\n /** True when a phone-side DIRECT Mapbox call can be made (user key saved). */\n public hasMapboxToken(): boolean {\n return !!resolveMapboxAccessToken()\n }\n\n /** True when the user saved their own Mapbox key in Settings > API Keys. */\n public hasUserMapboxKey(): boolean {\n return !!userMapboxApiKey()\n }\n\n /**\n * Type-ahead place search on-device with the user's own Mapbox key.\n * Preferred over the cloud maps service whenever that key is set — see\n * {@link placeAutocompleteViaSearchBox}.\n */\n public async placeAutocomplete(\n query: string,\n near: {lat: number; lng: number} | undefined,\n sessionToken: string,\n ): Promise<{\n ok: boolean\n suggestions?: Array<{placeId: string; mainText: string; secondaryText: string; distanceMeters?: number}>\n error?: string\n }> {\n return placeAutocompleteViaSearchBox(query, near, sessionToken)\n }\n\n /** Resolve a suggestion to coordinates on-device. Pairs with {@link placeAutocomplete}. */\n public async placeDetails(\n placeId: string,\n sessionToken: string,\n ): Promise<{\n ok: boolean\n place?: {placeId: string; name: string; address: string; lat: number; lng: number}\n error?: string\n }> {\n return placeDetailsViaSearchBox(placeId, sessionToken)\n }\n\n private attachNativeSubs(): void {\n console.log(`${LOG_TAG}: attachNativeSubs() — listeners=${this.listeners.size}`)\n this.subs.push(\n CrustModule.addListener(\"onNavManeuver\", (data) => {\n this.state = \"navigating\"\n const event: NavManeuver = {kind: \"maneuver\", ...data}\n this.lastManeuver = event\n this.fanout(event)\n }),\n CrustModule.addListener(\"onNavRerouting\", () => {\n console.log(`${LOG_TAG}: ← onNavRerouting`)\n this.state = \"rerouting\"\n this.fanout({kind: \"rerouting\"})\n }),\n CrustModule.addListener(\"onNavArrived\", () => {\n console.log(`${LOG_TAG}: ← onNavArrived`)\n this.state = \"arrived\"\n this.lastManeuver = null\n this.fanout({kind: \"arrived\"})\n }),\n CrustModule.addListener(\"onNavError\", (data) => {\n console.log(`${LOG_TAG}: ← onNavError`, data?.message)\n this.fanout({kind: \"error\", message: data.message})\n }),\n CrustModule.addListener(\"onNavLocation\", (data) => {\n const loc: NavLocation = {\n lat: data.lat,\n lng: data.lng,\n accuracy: data.accuracy ?? null,\n timestamp: data.timestamp,\n }\n this.locationListeners.forEach((l) => {\n try {\n l(loc)\n } catch (err) {\n console.error(`${LOG_TAG}: location listener threw`, err)\n }\n })\n }),\n CrustModule.addListener(\"onNavRoute\", (data) => {\n const route: NavRoute = {\n points: data.points ?? [],\n steps: data.steps?.map((step) => ({\n ...step,\n road: step.road ?? null,\n })),\n }\n this.lastRoute = route\n console.log(`${LOG_TAG}: ← onNavRoute (${route.points.length} points, steps=${route.steps?.length ?? \"null\"})`)\n this.routeListeners.forEach((l) => {\n try {\n l(route)\n } catch (err) {\n console.error(`${LOG_TAG}: route listener threw`, err)\n }\n })\n }),\n CrustModule.addListener(\"onNavOffRoute\", (data) => {\n console.log(`${LOG_TAG}: ← onNavOffRoute`, data?.offRouteDistanceMeters)\n this.fanout({kind: \"off_route\", offRouteDistanceMeters: data?.offRouteDistanceMeters ?? 0})\n }),\n )\n }\n\n private detachNativeSubs(): void {\n this.subs.forEach((s) => s.remove())\n this.subs = []\n }\n\n private fanout(update: NavUpdate): void {\n this.listeners.forEach((l) => {\n try {\n l(update)\n } catch (err) {\n console.error(`${LOG_TAG}: listener threw`, err)\n }\n })\n }\n}\n\nconst navigationService = NavigationService.getInstance()\nexport default navigationService\n\n// ---------------------------------------------------------------------------\n// Routes API (REST)\n// ---------------------------------------------------------------------------\n\n// Routes + Geocoding go DIRECT to Mapbox from the phone process ONLY when the\n// user saved their own key (Settings > API Keys) — \"use my account\". Without\n// one, callers (NavigationHandlers) route these operations through the v2\n// cloud maps proxy instead; the binary ships no baked Mapbox key.\nconst MAPBOX_DIRECTIONS_BASE = \"https://api.mapbox.com/directions/v5/mapbox\"\nconst MAPBOX_GEOCODE_REVERSE = \"https://api.mapbox.com/search/geocode/v6/reverse\"\nconst MAPBOX_SEARCHBOX_SUGGEST = \"https://api.mapbox.com/search/searchbox/v1/suggest\"\n\n/** Place search sits in front of a voice command; a stalled call must fail over, not hang. */\nconst PLACE_SEARCH_TIMEOUT_MS = 6_000\n\nasync function fetchWithTimeout(url: string, timeoutMs: number): Promise<Response> {\n const controller = new AbortController()\n const timer = BgTimer.setTimeout(() => controller.abort(), timeoutMs)\n try {\n return await fetch(url, {method: \"GET\", signal: controller.signal})\n } finally {\n BgTimer.clearTimeout(timer)\n }\n}\nconst MAPBOX_SEARCHBOX_RETRIEVE = \"https://api.mapbox.com/search/searchbox/v1/retrieve\"\n\n/**\n * The Mapbox token for phone-side REST calls: the user's key\n * (Settings > Keys) or nothing — empty means \"use the cloud maps proxy\".\n */\nfunction mapboxToken(): string {\n return resolveMapboxAccessToken()\n}\n\n/**\n * Phone-side helper: hit the Mapbox Directions API directly with the user's own\n * key (Settings > API Keys). Preferred over the v2 cloud maps service whenever\n * that key is set, so routing works without the cloud. Lives here\n * (not in Kotlin) so it's platform-independent across the JS bridge.\n * Returns the SDK-shaped result with primary + alternates.\n *\n * Mapbox Directions differs from Google Routes in shape: numeric\n * `distance`/`duration`, `polyline6` geometry per-route AND per-step, and\n * `maneuver = {location:[lng,lat], type, modifier, instruction}`. We\n * synthesize the SDK's `ComputedRouteStep` (lat/lng start, endLat/endLng\n * = next step's start) from the ordered step list.\n */\nasync function computeRouteViaRoutesApi(payload: Record<string, unknown>): Promise<{\n ok: boolean\n error?: string\n routes?: Array<{\n points: Array<{lat: number; lng: number}>\n totalDistanceMeters: number\n totalDurationSeconds: number\n summary?: string\n steps?: Array<{\n lat: number\n lng: number\n endLat: number\n endLng: number\n distanceMeters: number\n maneuver?: string\n instruction?: string\n road?: string | null\n }>\n }>\n}> {\n const origin = payload.origin as {lat?: unknown; lng?: unknown} | undefined\n const stopsRaw = payload.stops as Array<{lat?: unknown; lng?: unknown}> | undefined\n const mode = (typeof payload.mode === \"string\" ? payload.mode : \"walking\").toLowerCase()\n const alt = Number(payload.alternatives)\n const alternatives = Number.isFinite(alt) && alt > 0 ? alt : 1\n const avoid = (payload.avoid as Record<string, unknown> | undefined) ?? {}\n\n const oLat = Number(origin?.lat)\n const oLng = Number(origin?.lng)\n if (!Number.isFinite(oLat) || !Number.isFinite(oLng)) {\n return {ok: false, error: \"computeRoute: origin.lat/lng required\"}\n }\n const stops = (Array.isArray(stopsRaw) ? stopsRaw : [])\n .map((s) => ({lat: Number(s?.lat), lng: Number(s?.lng)}))\n .filter((s) => Number.isFinite(s.lat) && Number.isFinite(s.lng))\n if (stops.length === 0) {\n return {ok: false, error: \"computeRoute: at least one stop required\"}\n }\n\n const token = mapboxToken()\n if (!token) return {ok: false, error: \"computeRoute: no Mapbox key saved (add yours in Settings > API Keys)\"}\n\n // Mapbox path is a semicolon-joined `lng,lat` list: origin then each stop.\n const coords = [`${oLng},${oLat}`, ...stops.map((s) => `${s.lng},${s.lat}`)].join(\";\")\n const exclude = mapboxExclude(avoid)\n const params = new URLSearchParams({\n alternatives: String(alternatives > 1),\n geometries: \"polyline6\",\n overview: \"full\",\n steps: \"true\",\n banner_instructions: \"true\",\n voice_instructions: \"false\",\n access_token: token,\n })\n if (exclude) params.set(\"exclude\", exclude)\n const url = `${MAPBOX_DIRECTIONS_BASE}/${mapboxProfile(mode)}/${coords}?${params.toString()}`\n\n try {\n const res = await fetch(url, {method: \"GET\"})\n if (!res.ok) {\n return {ok: false, error: `Directions API ${res.status}`}\n }\n const json = (await res.json()) as {\n code?: string\n message?: string\n routes?: Array<{\n geometry?: string\n distance?: number\n duration?: string | number\n weight_name?: string\n legs?: Array<{\n summary?: string\n steps?: Array<{\n geometry?: string\n name?: string\n distance?: number\n maneuver?: {location?: [number, number]; type?: string; modifier?: string; instruction?: string}\n }>\n }>\n }>\n }\n if (json.code && json.code !== \"Ok\") {\n return {ok: false, error: json.message ?? `Directions code ${json.code}`}\n }\n // Resolve `road` for every step whose Mapbox `name` was blank (slip\n // lanes, unnamed paths, arrival legs) via reverse-geocode. Per-route\n // and per-alternate resolution fire concurrently.\n const routes = await Promise.all(\n (json.routes ?? []).slice(0, alternatives).map(async (r) => {\n const legs = r.legs ?? []\n const flatSteps = legs.flatMap((leg) => leg.steps ?? [])\n const rawSteps = flatSteps.map((s, i) => {\n const here = s.maneuver?.location // [lng, lat]\n const next = flatSteps[i + 1]?.maneuver?.location\n const lat = here?.[1] ?? Number.NaN\n const lng = here?.[0] ?? Number.NaN\n return {\n lat,\n lng,\n // End of step i == start of step i+1; final step ends at itself.\n endLat: next?.[1] ?? lat,\n endLng: next?.[0] ?? lng,\n distanceMeters: Math.round(s.distance ?? 0),\n maneuver: mapboxManeuverToKind(s.maneuver?.type, s.maneuver?.modifier),\n instruction: s.maneuver?.instruction,\n // Mapbox gives the road name inline as `step.name`; prefer it\n // over geocoding. Blank names fall through to resolveStepRoads.\n road: s.name && s.name.trim().length > 0 ? s.name.trim() : undefined,\n }\n })\n const steps = await resolveStepRoads(rawSteps, reverseGeocodeRoadViaGeocodingApi)\n return {\n points: decodePolyline(r.geometry ?? \"\", 6),\n totalDistanceMeters: Math.round(r.distance ?? 0),\n totalDurationSeconds: parseDurationSeconds(r.duration ?? 0),\n summary: legs[0]?.summary,\n steps: steps.length > 0 ? steps : undefined,\n }\n }),\n )\n if (routes.length === 0) return {ok: false, error: \"no routes returned\"}\n return {ok: true, routes}\n } catch (err) {\n return {ok: false, error: err instanceof Error ? err.message : \"computeRoute failed\"}\n }\n}\n\n/** SDK-agnostic mode → Mapbox Directions profile. two_wheeler → driving. */\nfunction mapboxProfile(mode: string): string {\n switch (mode) {\n case \"walking\":\n return \"walking\"\n case \"cycling\":\n return \"cycling\"\n case \"two_wheeler\":\n return \"driving\"\n default:\n return \"driving-traffic\"\n }\n}\n\n/** Avoid flags → Mapbox `exclude` param. Null when nothing to exclude. */\nfunction mapboxExclude(avoid: Record<string, unknown>): string | null {\n const ex: string[] = []\n if (avoid.tolls === true) ex.push(\"toll\")\n if (avoid.ferries === true) ex.push(\"ferry\")\n if (avoid.highways === true) ex.push(\"motorway\")\n return ex.length > 0 ? ex.join(\",\") : null\n}\n\n/**\n * Map Mapbox `maneuver.type` + `modifier` to the SDK's ManeuverKind\n * vocabulary — the JS-side mirror of NavigationManager.kt's mapManeuver\n * (issues/mapbox-navigation-migration.md §7). Kept here so the\n * computeRoute preview path labels turns the same way the live trip does.\n */\nfunction mapboxManeuverToKind(type?: string, modifier?: string): string | undefined {\n switch (type) {\n case \"depart\":\n return \"DEPART\"\n case \"arrive\":\n return \"ARRIVE\"\n case \"new name\":\n return \"NAME_CHANGE\"\n case \"continue\":\n case \"merge\":\n return \"CONTINUE\"\n case \"notification\":\n return \"STRAIGHT\"\n default:\n break\n }\n switch (modifier) {\n case \"uturn\":\n return \"U_TURN\"\n case \"sharp left\":\n return \"SHARP_LEFT\"\n case \"left\":\n return \"TURN_LEFT\"\n case \"slight left\":\n return \"SLIGHT_LEFT\"\n case \"straight\":\n return \"STRAIGHT\"\n case \"slight right\":\n return \"SLIGHT_RIGHT\"\n case \"right\":\n return \"TURN_RIGHT\"\n case \"sharp right\":\n return \"SHARP_RIGHT\"\n default:\n return type ? \"STRAIGHT\" : undefined\n }\n}\n\n/**\n * Reverse-geocode a coordinate via the Mapbox Geocoding v6 API directly, using\n * the user's own key (Settings > API Keys). Preferred over the v2 cloud maps\n * service whenever that key is set, so pin labels work without the cloud.\n *\n * Returns the road/street name (e.g. \"Octavia Blvd\") plus the full formatted\n * `address` for dropped-pin / POI labels. When no street is\n * present — the coordinate is genuinely off-grid (water, park interior) —\n * resolves with `{ok: true, road: null}`. Network failures and missing\n * token resolve with `{ok: false, error}`.\n *\n * Mapbox v6 returns a GeoJSON FeatureCollection; the street name lives at\n * `features[0].properties.context.street.name`. We also accept a feature\n * whose own `feature_type` is `street` (its `name` is the road). We prefer\n * the most-specific feature (the first), matching how the Google-era code\n * took the first `route` component.\n */\nasync function reverseGeocodeRoadViaGeocodingApi(coord: {lat: number; lng: number}): Promise<{\n ok: boolean\n road?: string | null\n address?: string | null\n error?: string\n}> {\n if (!Number.isFinite(coord.lat) || !Number.isFinite(coord.lng)) {\n return {ok: false, error: \"reverseGeocode: invalid coord\"}\n }\n const token = mapboxToken()\n if (!token)\n return {\n ok: false,\n error: \"reverseGeocode: no Mapbox key saved (add yours in Settings > API Keys)\",\n }\n const params = new URLSearchParams({\n longitude: String(coord.lng),\n latitude: String(coord.lat),\n // Bias toward address/street features so the street context is present.\n types: \"address,street\",\n limit: \"1\",\n access_token: token,\n })\n try {\n const res = await fetch(`${MAPBOX_GEOCODE_REVERSE}?${params.toString()}`, {method: \"GET\"})\n if (!res.ok) return {ok: false, error: `Geocoding API ${res.status}`}\n const json = (await res.json()) as {\n features?: Array<{\n properties?: {\n feature_type?: string\n name?: string\n full_address?: string\n place_formatted?: string\n context?: {street?: {name?: string}}\n }\n }>\n }\n // The full formatted address for dropped-pin / POI labels, taken from the\n // most-specific feature. Same precedence as the cloud provider so both\n // paths label a pin identically.\n const first = json.features?.[0]?.properties\n const address = (first?.full_address ?? first?.name ?? first?.place_formatted ?? \"\").trim() || null\n\n for (const feature of json.features ?? []) {\n const props = feature.properties\n // A street-type feature's own name is the road; otherwise read the\n // street from context.\n const fromStreetType = props?.feature_type === \"street\" ? props?.name : undefined\n const name = (fromStreetType ?? props?.context?.street?.name ?? \"\").trim()\n if (name) return {ok: true, road: name, address}\n }\n return {ok: true, road: null, address}\n } catch (err) {\n return {ok: false, error: err instanceof Error ? err.message : \"reverseGeocode failed\"}\n }\n}\n\n/**\n * Type-ahead place search straight from the device via Mapbox Search Box,\n * using the user's own key (Settings > API Keys). This is the offline-from-\n * the-cloud path: with a key saved, place search works with no runtime\n * involvement at all.\n *\n * Field extraction mirrors the cloud provider so both paths return identical\n * suggestions: only entries carrying a `mapbox_id` survive (without one there\n * is nothing to retrieve later), and the secondary line prefers\n * `place_formatted` over `full_address`.\n *\n * An empty query short-circuits to no suggestions — Search Box answers 422 for\n * a blank `q`. A missing token resolves `{ok: false}` so the caller can fall\n * back to the cloud.\n */\nasync function placeAutocompleteViaSearchBox(\n query: string,\n near: {lat: number; lng: number} | undefined,\n sessionToken: string,\n): Promise<{\n ok: boolean\n suggestions?: Array<{placeId: string; mainText: string; secondaryText: string; distanceMeters?: number}>\n error?: string\n}> {\n if (!query.trim()) return {ok: true, suggestions: []}\n const token = mapboxToken()\n if (!token) {\n return {\n ok: false,\n error: \"placeAutocomplete: no Mapbox key saved (add yours in Settings > API Keys)\",\n }\n }\n const params = new URLSearchParams({\n q: query,\n access_token: token,\n session_token: sessionToken,\n // POIs + addresses + places — the things a user navigates to.\n types: \"poi,address,place,street\",\n limit: \"10\",\n })\n // Mapbox wants lng,lat for proximity bias; `origin` adds per-suggestion distance.\n if (near) {\n params.set(\"proximity\", `${near.lng},${near.lat}`)\n params.set(\"origin\", `${near.lng},${near.lat}`)\n }\n\n try {\n const res = await fetchWithTimeout(`${MAPBOX_SEARCHBOX_SUGGEST}?${params.toString()}`, PLACE_SEARCH_TIMEOUT_MS)\n if (!res.ok) return {ok: false, error: `Search Box suggest ${res.status}`}\n const json = (await res.json()) as {\n suggestions?: Array<{\n mapbox_id?: string\n name?: string\n place_formatted?: string\n full_address?: string\n distance?: number\n }>\n }\n const suggestions = (json.suggestions ?? [])\n .filter((s): s is {mapbox_id: string} & typeof s => !!s.mapbox_id)\n .map((s) => ({\n placeId: s.mapbox_id,\n mainText: s.name ?? \"\",\n secondaryText: s.place_formatted ?? s.full_address ?? \"\",\n ...(typeof s.distance === \"number\" ? {distanceMeters: s.distance} : {}),\n }))\n return {ok: true, suggestions}\n } catch (err) {\n return {ok: false, error: err instanceof Error ? err.message : \"placeAutocomplete failed\"}\n }\n}\n\n/**\n * Resolve a Search Box suggestion to a full place with coordinates, using the\n * user's own key. Pairs with {@link placeAutocompleteViaSearchBox} — the same\n * `sessionToken` must thread both calls so Mapbox bills the keystrokes plus\n * this retrieve as one search session.\n *\n * Retrieve answers a GeoJSON FeatureCollection; coordinates live at\n * `features[0].geometry.coordinates` as [lng, lat].\n */\nasync function placeDetailsViaSearchBox(\n placeId: string,\n sessionToken: string,\n): Promise<{\n ok: boolean\n place?: {placeId: string; name: string; address: string; lat: number; lng: number}\n error?: string\n}> {\n const token = mapboxToken()\n if (!token) {\n return {\n ok: false,\n error: \"placeDetails: no Mapbox key saved (add yours in Settings > API Keys)\",\n }\n }\n const params = new URLSearchParams({access_token: token, session_token: sessionToken})\n try {\n const res = await fetchWithTimeout(\n `${MAPBOX_SEARCHBOX_RETRIEVE}/${encodeURIComponent(placeId)}?${params.toString()}`,\n PLACE_SEARCH_TIMEOUT_MS,\n )\n if (!res.ok) return {ok: false, error: `Search Box retrieve ${res.status}`}\n const json = (await res.json()) as {\n features?: Array<{\n geometry?: {coordinates?: [number, number]}\n properties?: {\n name?: string\n full_address?: string\n place_formatted?: string\n }\n }>\n }\n const feature = json.features?.[0]\n const coords = feature?.geometry?.coordinates\n if (!coords || coords.length < 2 || !Number.isFinite(coords[0]) || !Number.isFinite(coords[1])) {\n return {ok: false, error: \"placeDetails: no coordinates for place\"}\n }\n const props = feature?.properties\n return {\n ok: true,\n place: {\n placeId,\n name: props?.name ?? \"\",\n address: props?.full_address ?? props?.place_formatted ?? \"\",\n lng: coords[0],\n lat: coords[1],\n },\n }\n } catch (err) {\n return {ok: false, error: err instanceof Error ? err.message : \"placeDetails failed\"}\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"controllers.d.ts","sourceRoot":"","sources":["../../src/services/controllers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,wBAAwB,CAAA;AAE9E,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,UAAU,CAAA;AAGhD,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;AAmD7E,iFAAiF;AACjF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,EAAE,CAErE;AAED,0CAA0C;AAC1C,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEpE;AAED,2EAA2E;AAC3E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAUxE;AAED,6DAA6D;AAC7D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,SAAS,GAAG,OAAO,CAE/E;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,SAAS,GAAG,gBAAgB,EAAE,CAE3G;AAED,wDAAwD;AACxD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,SAAS,GAAG,MAAM,CAKlG"}
1
+ {"version":3,"file":"controllers.d.ts","sourceRoot":"","sources":["../../src/services/controllers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,wBAAwB,CAAA;AAE9E,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,UAAU,CAAA;AAGhD,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;AAoD7E,iFAAiF;AACjF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,EAAE,CAErE;AAED,0CAA0C;AAC1C,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEpE;AAED,2EAA2E;AAC3E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAUxE;AAED,6DAA6D;AAC7D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,SAAS,GAAG,OAAO,CAE/E;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,SAAS,GAAG,gBAAgB,EAAE,CAE3G;AAED,wDAAwD;AACxD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,SAAS,GAAG,MAAM,CAKlG"}
@@ -42,6 +42,7 @@ const INPUT_SURFACES = {
42
42
  [ControllerTypes.GAMEBRICK]: [GAMEBRICK_SURFACE],
43
43
  [ControllerTypes.IINE_ANANKE]: [GAMEBRICK_SURFACE],
44
44
  [ControllerTypes.ZERO2]: [GAMEBRICK_SURFACE],
45
+ [ControllerTypes.MICRO]: [GAMEBRICK_SURFACE],
45
46
  [ControllerTypes.R1]: [],
46
47
  };
47
48
  /** The input surfaces a connected controller of `model` adds to the glasses'. */
@@ -1 +1 @@
1
- {"version":3,"file":"controllers.js","sourceRoot":"","sources":["../../src/services/controllers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Controller registry read-model: the paired records (the native-authoritative\n * `controllers` setting) and the live driver statuses (glasses status\n * `controllers`), plus what each model adds to the input surfaces. Pure.\n */\nimport type {ControllerStatus, PairedController} from \"@glassly/bluetooth-sdk\"\n\nimport type {ButtonCapabilities} from \"../types\"\nimport {ControllerTypes} from \"../types/enums\"\n\nexport type InputSurface = NonNullable<ButtonCapabilities[\"buttons\"]>[number]\n\n/** The Neural Band's thumb swipes, pinches and dial. */\nconst NEURAL_BAND_SURFACE: InputSurface = {\n type: \"swipe2d\",\n events: [\n \"TAP\",\n \"DOUBLE_TAP\",\n \"PRESS_HOLD\",\n \"SWIPE_UP\",\n \"SWIPE_DOWN\",\n \"SWIPE_LEFT\",\n \"SWIPE_RIGHT\",\n \"DIAL_UP\",\n \"DIAL_DOWN\",\n ],\n}\n\n/** A watch trackpad's taps and four-way swipes, and the crown (Apple) or rotary bezel (Wear OS) as the dial. */\nconst WATCH_SURFACE: InputSurface = {\n type: \"swipe2d\",\n events: [\n \"TAP\",\n \"DOUBLE_TAP\",\n \"PRESS_HOLD\",\n \"SWIPE_UP\",\n \"SWIPE_DOWN\",\n \"SWIPE_LEFT\",\n \"SWIPE_RIGHT\",\n \"DIAL_UP\",\n \"DIAL_DOWN\",\n ],\n}\n\n/** The Gamebrick's D-pad is four absolute swipes; A is the press lifecycle (tap and hold) and B a double tap. */\nconst GAMEBRICK_SURFACE: InputSurface = {\n type: \"swipe2d\",\n events: [\"TAP\", \"DOUBLE_TAP\", \"PRESS_HOLD\", \"SWIPE_UP\", \"SWIPE_DOWN\", \"SWIPE_LEFT\", \"SWIPE_RIGHT\"],\n}\n\n// The R1 swipes up/down like the temples it stands in for, so it adds nothing.\nconst INPUT_SURFACES: Readonly<Record<string, readonly InputSurface[]>> = {\n [ControllerTypes.NEURAL_BAND]: [NEURAL_BAND_SURFACE],\n [ControllerTypes.APPLE_WATCH]: [WATCH_SURFACE],\n [ControllerTypes.WEAR_OS]: [WATCH_SURFACE],\n [ControllerTypes.GAMEBRICK]: [GAMEBRICK_SURFACE],\n [ControllerTypes.IINE_ANANKE]: [GAMEBRICK_SURFACE],\n [ControllerTypes.ZERO2]: [GAMEBRICK_SURFACE],\n [ControllerTypes.R1]: [],\n}\n\n/** The input surfaces a connected controller of `model` adds to the glasses'. */\nexport function controllerInputSurfaces(model: string): InputSurface[] {\n return (INPUT_SURFACES[model] ?? []).map((surface) => ({...surface, events: [...surface.events]}))\n}\n\n/** The model swipes in two dimensions. */\nexport function hasInput2d(model: string): boolean {\n return (INPUT_SURFACES[model] ?? []).some((surface) => surface.type === \"swipe2d\")\n}\n\nexport function isControllerModel(model: string | undefined): boolean {\n return model !== undefined && (Object.values(ControllerTypes) as string[]).includes(model)\n}\n\n/** The `controllers` setting as records; malformed entries are dropped. */\nexport function pairedControllersFrom(value: unknown): PairedController[] {\n if (!Array.isArray(value)) return []\n const records: PairedController[] = []\n for (const entry of value) {\n if (!entry || typeof entry !== \"object\") continue\n const {id, model, name} = entry as Record<string, unknown>\n if (typeof id !== \"string\" || !id || typeof model !== \"string\") continue\n records.push({id, model, name: typeof name === \"string\" ? name : id})\n }\n return records\n}\n\n/** Delivering input: link up and the route or claim done. */\nexport function isControllerReady(status: ControllerStatus | undefined): boolean {\n return status?.connected === true && status.fullyBooted === true\n}\n\nexport function readyControllers(statuses: Record<string, ControllerStatus> | undefined): ControllerStatus[] {\n return Object.values(statuses ?? {}).filter(isControllerReady)\n}\n\n/** Change key over the controllers delivering input. */\nexport function readyControllersKey(statuses: Record<string, ControllerStatus> | undefined): string {\n return readyControllers(statuses)\n .map((status) => `${status.id}=${status.model}`)\n .sort()\n .join(\",\")\n}\n"]}
1
+ {"version":3,"file":"controllers.js","sourceRoot":"","sources":["../../src/services/controllers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Controller registry read-model: the paired records (the native-authoritative\n * `controllers` setting) and the live driver statuses (glasses status\n * `controllers`), plus what each model adds to the input surfaces. Pure.\n */\nimport type {ControllerStatus, PairedController} from \"@glassly/bluetooth-sdk\"\n\nimport type {ButtonCapabilities} from \"../types\"\nimport {ControllerTypes} from \"../types/enums\"\n\nexport type InputSurface = NonNullable<ButtonCapabilities[\"buttons\"]>[number]\n\n/** The Neural Band's thumb swipes, pinches and dial. */\nconst NEURAL_BAND_SURFACE: InputSurface = {\n type: \"swipe2d\",\n events: [\n \"TAP\",\n \"DOUBLE_TAP\",\n \"PRESS_HOLD\",\n \"SWIPE_UP\",\n \"SWIPE_DOWN\",\n \"SWIPE_LEFT\",\n \"SWIPE_RIGHT\",\n \"DIAL_UP\",\n \"DIAL_DOWN\",\n ],\n}\n\n/** A watch trackpad's taps and four-way swipes, and the crown (Apple) or rotary bezel (Wear OS) as the dial. */\nconst WATCH_SURFACE: InputSurface = {\n type: \"swipe2d\",\n events: [\n \"TAP\",\n \"DOUBLE_TAP\",\n \"PRESS_HOLD\",\n \"SWIPE_UP\",\n \"SWIPE_DOWN\",\n \"SWIPE_LEFT\",\n \"SWIPE_RIGHT\",\n \"DIAL_UP\",\n \"DIAL_DOWN\",\n ],\n}\n\n/** The Gamebrick's D-pad is four absolute swipes; A is the press lifecycle (tap and hold) and B a double tap. */\nconst GAMEBRICK_SURFACE: InputSurface = {\n type: \"swipe2d\",\n events: [\"TAP\", \"DOUBLE_TAP\", \"PRESS_HOLD\", \"SWIPE_UP\", \"SWIPE_DOWN\", \"SWIPE_LEFT\", \"SWIPE_RIGHT\"],\n}\n\n// The R1 swipes up/down like the temples it stands in for, so it adds nothing.\nconst INPUT_SURFACES: Readonly<Record<string, readonly InputSurface[]>> = {\n [ControllerTypes.NEURAL_BAND]: [NEURAL_BAND_SURFACE],\n [ControllerTypes.APPLE_WATCH]: [WATCH_SURFACE],\n [ControllerTypes.WEAR_OS]: [WATCH_SURFACE],\n [ControllerTypes.GAMEBRICK]: [GAMEBRICK_SURFACE],\n [ControllerTypes.IINE_ANANKE]: [GAMEBRICK_SURFACE],\n [ControllerTypes.ZERO2]: [GAMEBRICK_SURFACE],\n [ControllerTypes.MICRO]: [GAMEBRICK_SURFACE],\n [ControllerTypes.R1]: [],\n}\n\n/** The input surfaces a connected controller of `model` adds to the glasses'. */\nexport function controllerInputSurfaces(model: string): InputSurface[] {\n return (INPUT_SURFACES[model] ?? []).map((surface) => ({...surface, events: [...surface.events]}))\n}\n\n/** The model swipes in two dimensions. */\nexport function hasInput2d(model: string): boolean {\n return (INPUT_SURFACES[model] ?? []).some((surface) => surface.type === \"swipe2d\")\n}\n\nexport function isControllerModel(model: string | undefined): boolean {\n return model !== undefined && (Object.values(ControllerTypes) as string[]).includes(model)\n}\n\n/** The `controllers` setting as records; malformed entries are dropped. */\nexport function pairedControllersFrom(value: unknown): PairedController[] {\n if (!Array.isArray(value)) return []\n const records: PairedController[] = []\n for (const entry of value) {\n if (!entry || typeof entry !== \"object\") continue\n const {id, model, name} = entry as Record<string, unknown>\n if (typeof id !== \"string\" || !id || typeof model !== \"string\") continue\n records.push({id, model, name: typeof name === \"string\" ? name : id})\n }\n return records\n}\n\n/** Delivering input: link up and the route or claim done. */\nexport function isControllerReady(status: ControllerStatus | undefined): boolean {\n return status?.connected === true && status.fullyBooted === true\n}\n\nexport function readyControllers(statuses: Record<string, ControllerStatus> | undefined): ControllerStatus[] {\n return Object.values(statuses ?? {}).filter(isControllerReady)\n}\n\n/** Change key over the controllers delivering input. */\nexport function readyControllersKey(statuses: Record<string, ControllerStatus> | undefined): string {\n return readyControllers(statuses)\n .map((status) => `${status.id}=${status.model}`)\n .sort()\n .join(\",\")\n}\n"]}