gps-plus-slam-app-framework 1.0.6 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/LICENSE +4 -4
  2. package/README.md +249 -108
  3. package/dist/accuracy-circles-CsxE_7x1.d.ts +43 -0
  4. package/dist/{app-selectors-CHt7DLuq.d.ts → app-selectors-BeU0_ab8.d.ts} +8 -10
  5. package/dist/ar/camera-blit-capture.d.ts +1 -1
  6. package/dist/ar/capture-failure-tracker.d.ts +1 -1
  7. package/dist/ar/chromium-camera-access-workaround.d.ts +1 -1
  8. package/dist/ar/depth-sampler.d.ts +2 -2
  9. package/dist/ar/frame-loop.d.ts +2 -0
  10. package/dist/ar/frame-loop.js +40 -0
  11. package/dist/ar/image-capture.d.ts +1 -1
  12. package/dist/ar/image-capture.js +1 -1
  13. package/dist/ar/index.d.ts +12 -12
  14. package/dist/ar/index.js +3 -3
  15. package/dist/ar/replay-scene.d.ts +1 -1
  16. package/dist/ar/scene-node-names.d.ts +1 -1
  17. package/dist/ar/webxr-session.d.ts +4 -4
  18. package/dist/ar/webxr-session.js +150 -55
  19. package/dist/ar/xr-camera-texture.d.ts +1 -1
  20. package/dist/ar/xr-error-handler.d.ts +1 -1
  21. package/dist/core/index.d.ts +2 -2
  22. package/dist/core/index.js +2 -2
  23. package/dist/create-slam-app-store-CNsZ3rcX.d.ts +371 -0
  24. package/dist/{depth-sampler-BNCtnEoP.d.ts → depth-sampler-xg8vna6c.d.ts} +1 -1
  25. package/dist/{file-system-DD5TczSO.d.ts → file-system-DTApEv_Q.d.ts} +32 -2
  26. package/dist/frame-loop-QJIxLin0.d.ts +42 -0
  27. package/dist/frustum-visibility-BHnFrSKQ.d.ts +58 -0
  28. package/dist/{fused-path-DtqCSqJh.d.ts → fused-path-CB4DwWOG.d.ts} +1 -1
  29. package/dist/geo/h3-proximity.d.ts +1 -1
  30. package/dist/geo/index.d.ts +1 -1
  31. package/dist/{geo-types-Xx-LVcnw.d.ts → geo-types-CTuF23gG.d.ts} +16 -1
  32. package/dist/{gps-GKc6_Cly.d.ts → gps-DXoQb9Kf.d.ts} +1 -1
  33. package/dist/gps-anchor-CnWY61XK.d.ts +48 -0
  34. package/dist/gps-anchor-DjC_3MoT.js +257 -0
  35. package/dist/{gps-ar-pose-sampler-D_Zso40V.d.ts → gps-ar-pose-sampler-DsM1Kb2N.d.ts} +1 -1
  36. package/dist/{gps-event-coordinator-fwvmVfku.d.ts → gps-event-coordinator-DBx9I1YX.d.ts} +3 -3
  37. package/dist/gps-event-markers-BGr-iLvi.d.ts +103 -0
  38. package/dist/{image-capture-2pKjYUS6.d.ts → image-capture-DZLxHDN9.d.ts} +1 -1
  39. package/dist/index-gzWJMVpo.d.ts +2 -0
  40. package/dist/index-pOjUCKEP.d.ts +24 -0
  41. package/dist/index.d.ts +58 -52
  42. package/dist/index.js +11 -5
  43. package/dist/{leaflet-map-overlay-CQZcnxbc.d.ts → leaflet-map-overlay-Cew7XAoO.d.ts} +22 -11
  44. package/dist/{logger-B81iwxx0.d.ts → logger-C9vugiQb.d.ts} +7 -1
  45. package/dist/map-data-sih4g64v.d.ts +49 -0
  46. package/dist/map-overlay-draw-B3R1c9Xp.d.ts +42 -0
  47. package/dist/{null-storage-backend-C0TiwwzQ.d.ts → null-storage-backend-BKOS7JpL.d.ts} +2 -2
  48. package/dist/{opfs-storage-backend-Gt3rd76D.d.ts → opfs-storage-backend-Cj_7PWoq.d.ts} +2 -2
  49. package/dist/{permission-checker-Cu3nbH1S.d.ts → permission-checker-DPJl_RU6.d.ts} +41 -1
  50. package/dist/persistence-middleware-BkHIqvaA.d.ts +55 -0
  51. package/dist/{recording-replayer-BFhFs7Mc.d.ts → recording-replayer-CmCIIZ02.d.ts} +2 -2
  52. package/dist/{recording-slice-BiktUIWF.d.ts → recording-slice-d6OtCrza.d.ts} +2 -2
  53. package/dist/{replay-engine-B88Va62x.d.ts → replay-engine-BGBRQyXs.d.ts} +1 -1
  54. package/dist/{replay-scene-DtUm6bsr.d.ts → replay-scene-DpAGcAKY.d.ts} +3 -3
  55. package/dist/sensors/gps-error-handler.d.ts +1 -1
  56. package/dist/sensors/gps.d.ts +1 -1
  57. package/dist/sensors/gps.js +2 -2
  58. package/dist/sensors/index.d.ts +3 -3
  59. package/dist/sensors/permission-checker.d.ts +2 -2
  60. package/dist/sensors/permission-checker.js +79 -1
  61. package/dist/state/app-selectors.d.ts +2 -2
  62. package/dist/state/app-selectors.js +33 -3
  63. package/dist/state/combined-root-state.d.ts +2 -0
  64. package/dist/state/combined-root-state.js +1 -0
  65. package/dist/state/create-slam-app-store.d.ts +1 -1
  66. package/dist/state/create-slam-app-store.js +27 -13
  67. package/dist/state/gps-ar-pose-sampler.d.ts +3 -3
  68. package/dist/state/gps-event-coordinator.d.ts +1 -1
  69. package/dist/state/index.d.ts +17 -16
  70. package/dist/state/index.js +6 -4
  71. package/dist/state/persistence-middleware.d.ts +2 -2
  72. package/dist/state/persistence-middleware.js +35 -7
  73. package/dist/state/recording-options.d.ts +1 -1
  74. package/dist/state/recording-replayer.d.ts +2 -2
  75. package/dist/state/recording-slice.d.ts +1 -1
  76. package/dist/state/replay-engine.d.ts +1 -1
  77. package/dist/state/store-subscribers.d.ts +2 -2
  78. package/dist/state/store-subscribers.js +38 -12
  79. package/dist/state/subscribe-to-selector.d.ts +1 -1
  80. package/dist/state/tracking-quality.d.ts +2 -0
  81. package/dist/state/tracking-quality.js +723 -0
  82. package/dist/state/tracking-slice.d.ts +2 -0
  83. package/dist/state/tracking-slice.js +147 -0
  84. package/dist/storage/file-system-utils.d.ts +1 -1
  85. package/dist/storage/file-system.d.ts +2 -2
  86. package/dist/storage/file-system.js +52 -1
  87. package/dist/storage/index.d.ts +8 -8
  88. package/dist/storage/null-storage-backend.d.ts +1 -1
  89. package/dist/storage/opfs-storage-backend.d.ts +1 -1
  90. package/dist/storage/opfs-storage.d.ts +1 -1
  91. package/dist/storage/storage-backend.d.ts +1 -1
  92. package/dist/storage/zip-export.d.ts +1 -1
  93. package/dist/storage/zip-reader.d.ts +1 -1
  94. package/dist/storage/zip-reader.js +8 -4
  95. package/dist/{storage-backend-yVnuWGTr.d.ts → storage-backend-CT0Il_AB.d.ts} +1 -1
  96. package/dist/{store-subscribers-DKKHld49.d.ts → store-subscribers-Dce_CoJF.d.ts} +31 -6
  97. package/dist/{subscribe-to-selector-ghDKYtap.d.ts → subscribe-to-selector-DIHm3BRZ.d.ts} +1 -1
  98. package/dist/test-utils/browser-mocks.d.ts +1 -1
  99. package/dist/test-utils/zip-round-trip-helpers.d.ts +7 -1
  100. package/dist/test-utils/zip-round-trip-helpers.js +2 -1
  101. package/dist/tracking-slice-utCNND8t.d.ts +86 -0
  102. package/dist/types/ar-types.d.ts +1 -1
  103. package/dist/types/geo-types.d.ts +2 -2
  104. package/dist/types/index.d.ts +3 -3
  105. package/dist/utils/concurrency.d.ts +1 -1
  106. package/dist/utils/failure-tracker.d.ts +1 -1
  107. package/dist/utils/format-file-size.d.ts +1 -1
  108. package/dist/utils/fused-path.d.ts +1 -1
  109. package/dist/utils/index.d.ts +6 -6
  110. package/dist/utils/list-formatter.d.ts +1 -1
  111. package/dist/utils/logger.d.ts +1 -1
  112. package/dist/utils/logger.js +68 -8
  113. package/dist/visualization/accuracy-circles.d.ts +2 -0
  114. package/dist/visualization/accuracy-circles.js +57 -0
  115. package/dist/visualization/alignment-lerper.d.ts +1 -1
  116. package/dist/visualization/camera-follower.d.ts +1 -1
  117. package/dist/visualization/css3d-renderer-manager.d.ts +1 -1
  118. package/dist/visualization/frustum-visibility.d.ts +2 -0
  119. package/dist/visualization/frustum-visibility.js +139 -0
  120. package/dist/visualization/gps-anchor.d.ts +2 -0
  121. package/dist/visualization/gps-anchor.js +2 -0
  122. package/dist/visualization/gps-compass-cubes.d.ts +1 -1
  123. package/dist/visualization/gps-event-markers.d.ts +2 -2
  124. package/dist/visualization/gps-event-markers.js +69 -2
  125. package/dist/visualization/index.d.ts +17 -12
  126. package/dist/visualization/index.js +6 -2
  127. package/dist/visualization/leaflet-map-overlay.d.ts +1 -1
  128. package/dist/visualization/leaflet-map-overlay.js +33 -79
  129. package/dist/visualization/lerp-utils.d.ts +1 -1
  130. package/dist/visualization/map-data.d.ts +2 -0
  131. package/dist/visualization/map-data.js +33 -0
  132. package/dist/visualization/map-overlay-draw.d.ts +2 -0
  133. package/dist/visualization/map-overlay-draw.js +107 -0
  134. package/dist/visualization/map-overlay.d.ts +1 -1
  135. package/dist/visualization/three-dispose.d.ts +1 -1
  136. package/dist/visualization/vis-colors.d.ts +1 -1
  137. package/dist/{webxr-session-COlSrXdL.d.ts → webxr-session-DB5cIZnN.d.ts} +53 -12
  138. package/dist/{zip-reader-KgJEXbca.d.ts → zip-reader-D1105idz.d.ts} +5 -0
  139. package/package.json +16 -16
  140. package/dist/ar/tracking-state.d.ts +0 -2
  141. package/dist/ar/tracking-state.js +0 -164
  142. package/dist/combined-root-state-B3SvPNjU.d.ts +0 -6
  143. package/dist/create-slam-app-store-DBm7g2Zd.d.ts +0 -85
  144. package/dist/gps-anchored-mesh-manager-CovAFK4g.d.ts +0 -56
  145. package/dist/gps-event-markers-sVyO9utS.d.ts +0 -67
  146. package/dist/persistence-middleware-z-75iisb.d.ts +0 -31
  147. package/dist/tracking-state-B9QfuZCg.d.ts +0 -101
  148. package/dist/visualization/gps-anchored-mesh-manager.d.ts +0 -2
  149. package/dist/visualization/gps-anchored-mesh-manager.js +0 -128
  150. /package/dist/{alignment-lerper-D9BeDwZX.d.ts → alignment-lerper-L1RbWHQ4.d.ts} +0 -0
  151. /package/dist/{ar-types-B-ORgk6Z.d.ts → ar-types-Ck8LEq8k.d.ts} +0 -0
  152. /package/dist/{camera-blit-capture-DHuyrrxr.d.ts → camera-blit-capture-C1V9I1Z6.d.ts} +0 -0
  153. /package/dist/{camera-follower-BMqPddxx.d.ts → camera-follower-1k8mnw5J.d.ts} +0 -0
  154. /package/dist/{capture-failure-tracker-2Q6oI2uQ.d.ts → capture-failure-tracker-JKb1ST8E.d.ts} +0 -0
  155. /package/dist/{chromium-camera-access-workaround-CU5zSKNr.d.ts → chromium-camera-access-workaround-NvChXsi8.d.ts} +0 -0
  156. /package/dist/{concurrency-p6gB30fT.d.ts → concurrency-CMw8pSaG.d.ts} +0 -0
  157. /package/dist/{css3d-renderer-manager-rgLMVAvd.d.ts → css3d-renderer-manager-CkjCb2HW.d.ts} +0 -0
  158. /package/dist/{failure-tracker-1sQ_Cgyw.d.ts → failure-tracker-DnHXOIRa.d.ts} +0 -0
  159. /package/dist/{file-system-utils-BH8FdyIu.d.ts → file-system-utils-CtKiiw27.d.ts} +0 -0
  160. /package/dist/{format-file-size-onGq0k1Q.d.ts → format-file-size-BTS5H62-.d.ts} +0 -0
  161. /package/dist/{gps-compass-cubes-jRIJMOuh.d.ts → gps-compass-cubes-CsLtFv4B.d.ts} +0 -0
  162. /package/dist/{gps-error-handler-CH1S528z.d.ts → gps-error-handler-Dg3ziRVY.d.ts} +0 -0
  163. /package/dist/{h3-proximity-GwesPTFT.d.ts → h3-proximity-BhfgNbdW.d.ts} +0 -0
  164. /package/dist/{lerp-utils-CZgQlrmu.d.ts → lerp-utils-B8MM8zCR.d.ts} +0 -0
  165. /package/dist/{list-formatter-DKQQVLcl.d.ts → list-formatter-CNqi-E2j.d.ts} +0 -0
  166. /package/dist/{map-overlay-C9ifl_4-.d.ts → map-overlay-DAmreyA3.d.ts} +0 -0
  167. /package/dist/{opfs-storage-Dlq1I_Gb.d.ts → opfs-storage-DOPkzgeT.d.ts} +0 -0
  168. /package/dist/{recording-options-BYUFX8iU.d.ts → recording-options-Dq6IsKAv.d.ts} +0 -0
  169. /package/dist/{scene-node-names-DPsaE2z3.d.ts → scene-node-names-6LBjPmwz.d.ts} +0 -0
  170. /package/dist/{three-dispose-qt_r5wR1.d.ts → three-dispose-C2drkp6f.d.ts} +0 -0
  171. /package/dist/{vis-colors-BKkdTIKb.d.ts → vis-colors-CHQhjal3.d.ts} +0 -0
  172. /package/dist/{xr-camera-texture-BbukNE79.d.ts → xr-camera-texture-BU5YvKAM.d.ts} +0 -0
  173. /package/dist/{xr-error-handler-DTHfmvrl.d.ts → xr-error-handler-CDY5QxGb.d.ts} +0 -0
  174. /package/dist/{zip-export-BjrQPv0X.d.ts → zip-export-QO4iLIi7.d.ts} +0 -0
@@ -1,6 +1,8 @@
1
- import { recordingReducer } from "./recording-slice.js";
2
- import { createPersistenceMiddleware } from "./persistence-middleware.js";
3
- import { arElementsReducer, gpsDataReducer, gpsElementsReducer, sanitizeForDevTools, validateLicenseKey } from "gps-plus-slam-js";
1
+ import { trackingReducer } from "./tracking-slice.js";
2
+ import { recordWriteFailure, recordingReducer } from "./recording-slice.js";
3
+ import { createTrackingQualityListenerMiddleware, trackingQualityReducer } from "./tracking-quality.js";
4
+ import { createPersistenceMiddleware, slicePrefixOf } from "./persistence-middleware.js";
5
+ import { arElementsReducer, gpsDataReducer, gpsElementsReducer, sanitizeForDevTools, setZeroPos, validateLicenseKey } from "gps-plus-slam-js";
4
6
  import { configureStore } from "@reduxjs/toolkit";
5
7
  import { COMMUNITY_LICENSE_KEY } from "gps-plus-slam-js/community-license-key";
6
8
  //#region ../src/state/create-slam-app-store.ts
@@ -22,27 +24,39 @@ import { COMMUNITY_LICENSE_KEY } from "gps-plus-slam-js/community-license-key";
22
24
  * @see docs/2026-05-03-appframework-vs-recorderapp-boundary-analysis.md — Iter 1
23
25
  */
24
26
  /**
27
+ * Slice prefixes the framework always persists, derived from the actual
28
+ * library / framework action creators (never hand-typed). A rename of the
29
+ * `gpsData` or `recording` slice therefore propagates here automatically
30
+ * instead of silently dropping that slice's actions from recordings.
31
+ */
32
+ const BUILTIN_PERSISTED_PREFIXES = [slicePrefixOf(setZeroPos.type), slicePrefixOf(recordWriteFailure.type)];
33
+ /**
25
34
  * Build a Redux store wired with library + recording slices, persistence
26
35
  * middleware, and any caller-supplied extras. See module docstring for the
27
36
  * design rationale.
28
37
  */
29
38
  function createSlamAppStore(options) {
30
- const { storageBackend, extraReducers, extraMiddleware, onWriteFailure, enableDevChecks = true, licenseKey = COMMUNITY_LICENSE_KEY } = options;
39
+ const { storageBackend, extraReducers, extraMiddleware, persistedExtraPrefixes, onWriteFailure, enableDevChecks = true, licenseKey = COMMUNITY_LICENSE_KEY, trackingQualityOptions } = options;
31
40
  validateLicenseKey(licenseKey);
41
+ const reducer = {
42
+ gpsData: gpsDataReducer,
43
+ gpsElements: gpsElementsReducer,
44
+ arElements: arElementsReducer,
45
+ recording: recordingReducer,
46
+ tracking: trackingReducer,
47
+ trackingQuality: trackingQualityReducer,
48
+ ...extraReducers ?? {}
49
+ };
50
+ const trackingQualityMiddleware = createTrackingQualityListenerMiddleware(trackingQualityOptions);
32
51
  const store = configureStore({
33
- reducer: {
34
- gpsData: gpsDataReducer,
35
- gpsElements: gpsElementsReducer,
36
- arElements: arElementsReducer,
37
- recording: recordingReducer,
38
- ...extraReducers ?? {}
39
- },
52
+ reducer,
40
53
  middleware: (getDefaultMiddleware) => getDefaultMiddleware({
41
54
  serializableCheck: enableDevChecks,
42
55
  immutableCheck: enableDevChecks
43
- }).concat(createPersistenceMiddleware({
56
+ }).prepend(trackingQualityMiddleware).concat(createPersistenceMiddleware({
44
57
  storageBackend,
45
- onWriteFailure
58
+ onWriteFailure,
59
+ persistedPrefixes: [...BUILTIN_PERSISTED_PREFIXES, ...persistedExtraPrefixes ?? []]
46
60
  }), ...extraMiddleware ?? []),
47
61
  devTools: {
48
62
  actionSanitizer: sanitizeForDevTools,
@@ -1,4 +1,4 @@
1
- import { t as ARPose } from "../ar-types-B-ORgk6Z.js";
2
- import { o as extractOdomPosition, s as extractOdomRotation } from "../gps-event-coordinator-fwvmVfku.js";
3
- import { i as captureGpsAnchorSample, n as GpsAnchorSample, r as GpsAnchorSampleGpsPoint, t as CaptureGpsAnchorSampleOptions } from "../gps-ar-pose-sampler-D_Zso40V.js";
1
+ import { t as ARPose } from "../ar-types-Ck8LEq8k.js";
2
+ import { o as extractOdomPosition, s as extractOdomRotation } from "../gps-event-coordinator-DBx9I1YX.js";
3
+ import { i as captureGpsAnchorSample, n as GpsAnchorSample, r as GpsAnchorSampleGpsPoint, t as CaptureGpsAnchorSampleOptions } from "../gps-ar-pose-sampler-DsM1Kb2N.js";
4
4
  export { ARPose, CaptureGpsAnchorSampleOptions, GpsAnchorSample, GpsAnchorSampleGpsPoint, captureGpsAnchorSample, extractOdomPosition, extractOdomRotation };
@@ -1,2 +1,2 @@
1
- import { a as eulerToQuaternion, c as getLastDeviceOrientation, i as createGpsPositionHandler, l as resetCoordinatorState, n as buildRawGpsPoint, o as extractOdomPosition, r as buildRecordGpsEventPayload, s as extractOdomRotation, t as RecordingCoordinatorConfig, u as updateDeviceOrientation } from "../gps-event-coordinator-fwvmVfku.js";
1
+ import { a as eulerToQuaternion, c as getLastDeviceOrientation, i as createGpsPositionHandler, l as resetCoordinatorState, n as buildRawGpsPoint, o as extractOdomPosition, r as buildRecordGpsEventPayload, s as extractOdomRotation, t as RecordingCoordinatorConfig, u as updateDeviceOrientation } from "../gps-event-coordinator-DBx9I1YX.js";
2
2
  export { RecordingCoordinatorConfig, buildRawGpsPoint, buildRecordGpsEventPayload, createGpsPositionHandler, eulerToQuaternion, extractOdomPosition, extractOdomRotation, getLastDeviceOrientation, resetCoordinatorState, updateDeviceOrientation };
@@ -1,16 +1,17 @@
1
- import { i as DepthSample, r as DepthPoint } from "../ar-types-B-ORgk6Z.js";
2
- import { _ as validateRecordingOptions, a as IMAGE_CONSTRAINTS, c as RecordingOptionsInput, d as loadRecordingOptions, f as resetRecordingOptions, g as validateImageOptions, h as validateDepthOptions, i as DepthCaptureOptions, l as STORAGE_KEY, n as DEFAULT_RECORDING_OPTIONS, o as ImageCaptureOptions, p as saveRecordingOptions, r as DEPTH_CONSTRAINTS, u as cloneRecordingOptions } from "../recording-options-BYUFX8iU.js";
3
- import { a as recordWriteFailure, i as recordDepthSample, n as SessionMetadata$1, o as recordingReducer, r as endSession, s as startSession, t as RecordingState } from "../recording-slice-BiktUIWF.js";
4
- import { n as SessionMetadata } from "../opfs-storage-Dlq1I_Gb.js";
5
- import { n as StorageBackend } from "../storage-backend-yVnuWGTr.js";
6
- import { a as SlamAppStoreOptions, i as SlamAppStore, n as SlamAppMiddleware, o as createSlamAppStore, r as SlamAppRootState, t as SlamAppCombinedState } from "../create-slam-app-store-DBm7g2Zd.js";
7
- import { a as eulerToQuaternion, c as getLastDeviceOrientation, i as createGpsPositionHandler, l as resetCoordinatorState, n as buildRawGpsPoint, o as extractOdomPosition, r as buildRecordGpsEventPayload, s as extractOdomRotation, t as RecordingCoordinatorConfig, u as updateDeviceOrientation } from "../gps-event-coordinator-fwvmVfku.js";
8
- import { i as captureGpsAnchorSample, n as GpsAnchorSample, r as GpsAnchorSampleGpsPoint, t as CaptureGpsAnchorSampleOptions } from "../gps-ar-pose-sampler-D_Zso40V.js";
9
- import { n as replayRecording, t as ReplayRecordingOptions } from "../recording-replayer-BFhFs7Mc.js";
10
- import { n as createPersistenceMiddleware, t as PersistenceMiddlewareOptions } from "../persistence-middleware-z-75iisb.js";
11
- import { a as ReplayAction, c as computeInterActionDelay, i as ProgressCallback, l as extractActionTimestamp, n as DEFAULT_MAX_DELAY_MS, o as ReplayEngine, r as ErrorCallback, s as ReplayState, t as CompleteCallback } from "../replay-engine-B88Va62x.js";
12
- import { n as subscribeToSelector, t as SubscribableStore } from "../subscribe-to-selector-ghDKYtap.js";
13
- import { n as wireStoreSubscribers, t as StoreSubscriberDeps } from "../store-subscribers-DKKHld49.js";
14
- import { a as selectReferencePoints, i as selectOdometryRotations, n as selectGpsPositions, o as selectZeroReference, r as selectOdometryPositions, t as selectAlignmentMatrix } from "../app-selectors-CHt7DLuq.js";
15
- import { GpsPoint, LatLong, MarkReferencePointPayload, RawDeviceOrientation, RawGpsPoint, RecordGpsEventPayload, add2dImage, calcRelativeCoordsInMeters, markReferencePoint, recordGpsEvent, setZeroPos } from "gps-plus-slam-js";
16
- export { type CaptureGpsAnchorSampleOptions, type CompleteCallback, DEFAULT_MAX_DELAY_MS, DEFAULT_RECORDING_OPTIONS, DEPTH_CONSTRAINTS, type DepthCaptureOptions, type DepthPoint, type DepthSample, type ErrorCallback, type GpsAnchorSample, type GpsAnchorSampleGpsPoint, type GpsPoint, IMAGE_CONSTRAINTS, type ImageCaptureOptions, type LatLong, type MarkReferencePointPayload, type SessionMetadata as OpfsSessionMetadata, type PersistenceMiddlewareOptions, type ProgressCallback, type RawDeviceOrientation, type RawGpsPoint, type RecordGpsEventPayload, type RecordingCoordinatorConfig, type RecordingOptionsInput, type RecordingState, type ReplayAction, ReplayEngine, type ReplayRecordingOptions, type ReplayState, STORAGE_KEY, type SessionMetadata$1 as SessionMetadata, type SlamAppCombinedState, type SlamAppMiddleware, type SlamAppRootState, type SlamAppStore, type SlamAppStoreOptions, type StorageBackend, type StoreSubscriberDeps, type SubscribableStore, add2dImage, buildRawGpsPoint, buildRecordGpsEventPayload, calcRelativeCoordsInMeters, captureGpsAnchorSample, cloneRecordingOptions, computeInterActionDelay, createGpsPositionHandler, createPersistenceMiddleware, createSlamAppStore, endSession, eulerToQuaternion, extractActionTimestamp, extractOdomPosition, extractOdomRotation, getLastDeviceOrientation, loadRecordingOptions, markReferencePoint, recordDepthSample, recordGpsEvent, recordWriteFailure, recordingReducer, replayRecording, resetCoordinatorState, resetRecordingOptions, saveRecordingOptions, selectAlignmentMatrix, selectGpsPositions, selectOdometryPositions, selectOdometryRotations, selectReferencePoints, selectZeroReference, setZeroPos, startSession, subscribeToSelector, updateDeviceOrientation, validateDepthOptions, validateImageOptions, validateRecordingOptions, wireStoreSubscribers };
1
+ import { i as DepthSample, r as DepthPoint } from "../ar-types-Ck8LEq8k.js";
2
+ import { a as TrackingSliceState, c as poseLost, d as selectLastRestartedPayload, f as selectLastSensorOrientation, g as trackingReducer, h as selectTrackingPhase, i as TrackingPhase, l as poseReceived, m as selectLostFrameCount, n as PoseReceivedPayload, o as clearLastRestartedPayload, p as selectLastValidPose, r as ResetTransformData, s as originReset, t as DeviceOrientation, u as resetTracking } from "../tracking-slice-utCNND8t.js";
3
+ import { _ as validateRecordingOptions, a as IMAGE_CONSTRAINTS, c as RecordingOptionsInput, d as loadRecordingOptions, f as resetRecordingOptions, g as validateImageOptions, h as validateDepthOptions, i as DepthCaptureOptions, l as STORAGE_KEY, n as DEFAULT_RECORDING_OPTIONS, o as ImageCaptureOptions, p as saveRecordingOptions, r as DEPTH_CONSTRAINTS, u as cloneRecordingOptions } from "../recording-options-Dq6IsKAv.js";
4
+ import { a as recordWriteFailure, i as recordDepthSample, n as SessionMetadata$1, o as recordingReducer, r as endSession, s as startSession, t as RecordingState } from "../recording-slice-d6OtCrza.js";
5
+ import { n as SessionMetadata } from "../opfs-storage-DOPkzgeT.js";
6
+ import { n as StorageBackend } from "../storage-backend-CT0Il_AB.js";
7
+ import { A as resetTrackingQuality, C as computeResidualConsensus, D as firstAgreementReached, E as degradedCountUpdated, F as snapshotsTrimmed, I as trackingQualityReducer, M as selectRecentAlignments, N as selectTrackingQuality, O as matrixDelta, P as snapshotPushed, S as computeGpsVsFusedDivergence, T as createTrackingQualityListenerMiddleware, _ as TrackingQualityState, a as SlamAppStoreOptions, b as computeCoverage, d as DEFAULT_TRACKING_QUALITY_OPTIONS, g as TrackingQualitySliceState, h as TrackingQualityReport, i as SlamAppStore, j as selectFirstAgreementObservationIndex, k as reportUpdated, m as TrackingQualityOptions, n as SlamAppMiddleware, o as createSlamAppStore, r as SlamAppRootState, s as AlignmentSnapshot, t as SlamAppCombinedState, v as computeCompassAgreement, w as computeTrackingQualityReport, x as computeGpsAccuracy, y as computeConvergence } from "../create-slam-app-store-CNsZ3rcX.js";
8
+ import { a as eulerToQuaternion, c as getLastDeviceOrientation, i as createGpsPositionHandler, l as resetCoordinatorState, n as buildRawGpsPoint, o as extractOdomPosition, r as buildRecordGpsEventPayload, s as extractOdomRotation, t as RecordingCoordinatorConfig, u as updateDeviceOrientation } from "../gps-event-coordinator-DBx9I1YX.js";
9
+ import { i as captureGpsAnchorSample, n as GpsAnchorSample, r as GpsAnchorSampleGpsPoint, t as CaptureGpsAnchorSampleOptions } from "../gps-ar-pose-sampler-DsM1Kb2N.js";
10
+ import { n as replayRecording, t as ReplayRecordingOptions } from "../recording-replayer-CmCIIZ02.js";
11
+ import { n as createPersistenceMiddleware, r as slicePrefixOf, t as PersistenceMiddlewareOptions } from "../persistence-middleware-BkHIqvaA.js";
12
+ import { a as ReplayAction, c as computeInterActionDelay, i as ProgressCallback, l as extractActionTimestamp, n as DEFAULT_MAX_DELAY_MS, o as ReplayEngine, r as ErrorCallback, s as ReplayState, t as CompleteCallback } from "../replay-engine-BGBRQyXs.js";
13
+ import { n as subscribeToSelector, t as SubscribableStore } from "../subscribe-to-selector-DIHm3BRZ.js";
14
+ import { n as wireStoreSubscribers, t as StoreSubscriberDeps } from "../store-subscribers-Dce_CoJF.js";
15
+ import { a as selectOdometryRotations, i as selectOdometryPositions, n as selectFrameTilesInWebXR, o as selectZeroReference, r as selectGpsPositions, t as selectAlignmentMatrix } from "../app-selectors-BeU0_ab8.js";
16
+ import { Add2dImagePayload, GpsPoint, LatLong, RawDeviceOrientation, RawGpsPoint, RecordGpsEventPayload, add2dImage, calcRelativeCoordsInMeters, recordGpsEvent, setZeroPos } from "gps-plus-slam-js";
17
+ export { type Add2dImagePayload, type AlignmentSnapshot, type CaptureGpsAnchorSampleOptions, type CompleteCallback, DEFAULT_MAX_DELAY_MS, DEFAULT_RECORDING_OPTIONS, DEFAULT_TRACKING_QUALITY_OPTIONS, DEPTH_CONSTRAINTS, type DepthCaptureOptions, type DepthPoint, type DepthSample, type DeviceOrientation, type ErrorCallback, type GpsAnchorSample, type GpsAnchorSampleGpsPoint, type GpsPoint, IMAGE_CONSTRAINTS, type ImageCaptureOptions, type LatLong, type SessionMetadata as OpfsSessionMetadata, type PersistenceMiddlewareOptions, type PoseReceivedPayload, type ProgressCallback, type RawDeviceOrientation, type RawGpsPoint, type RecordGpsEventPayload, type RecordingCoordinatorConfig, type RecordingOptionsInput, type RecordingState, type ReplayAction, ReplayEngine, type ReplayRecordingOptions, type ReplayState, type ResetTransformData, STORAGE_KEY, type SessionMetadata$1 as SessionMetadata, type SlamAppCombinedState, type SlamAppMiddleware, type SlamAppRootState, type SlamAppStore, type SlamAppStoreOptions, type StorageBackend, type StoreSubscriberDeps, type SubscribableStore, type TrackingPhase, type TrackingQualityOptions, type TrackingQualityReport, type TrackingQualitySliceState, type TrackingQualityState, type TrackingSliceState, add2dImage, buildRawGpsPoint, buildRecordGpsEventPayload, calcRelativeCoordsInMeters, captureGpsAnchorSample, clearLastRestartedPayload, cloneRecordingOptions, computeCompassAgreement, computeConvergence, computeCoverage, computeGpsAccuracy, computeGpsVsFusedDivergence, computeInterActionDelay, computeResidualConsensus, computeTrackingQualityReport, createGpsPositionHandler, createPersistenceMiddleware, createSlamAppStore, createTrackingQualityListenerMiddleware, degradedCountUpdated, endSession, eulerToQuaternion, extractActionTimestamp, extractOdomPosition, extractOdomRotation, firstAgreementReached, getLastDeviceOrientation, loadRecordingOptions, matrixDelta, originReset, poseLost, poseReceived, recordDepthSample, recordGpsEvent, recordWriteFailure, recordingReducer, replayRecording, reportUpdated, resetCoordinatorState, resetRecordingOptions, resetTracking, resetTrackingQuality, saveRecordingOptions, selectAlignmentMatrix, selectFirstAgreementObservationIndex, selectFrameTilesInWebXR, selectGpsPositions, selectLastRestartedPayload, selectLastSensorOrientation, selectLastValidPose, selectLostFrameCount, selectOdometryPositions, selectOdometryRotations, selectRecentAlignments, selectTrackingPhase, selectTrackingQuality, selectZeroReference, setZeroPos, slicePrefixOf, snapshotPushed, snapshotsTrimmed, startSession, subscribeToSelector, trackingQualityReducer, trackingReducer, updateDeviceOrientation, validateDepthOptions, validateImageOptions, validateRecordingOptions, wireStoreSubscribers };
@@ -1,13 +1,15 @@
1
1
  import { buildRawGpsPoint, buildRecordGpsEventPayload, createGpsPositionHandler, eulerToQuaternion, extractOdomPosition, extractOdomRotation, getLastDeviceOrientation, resetCoordinatorState, updateDeviceOrientation } from "./gps-event-coordinator.js";
2
+ import { clearLastRestartedPayload, originReset, poseLost, poseReceived, resetTracking, selectLastRestartedPayload, selectLastSensorOrientation, selectLastValidPose, selectLostFrameCount, selectTrackingPhase, trackingReducer } from "./tracking-slice.js";
2
3
  import { DEFAULT_RECORDING_OPTIONS, DEPTH_CONSTRAINTS, IMAGE_CONSTRAINTS, STORAGE_KEY, cloneRecordingOptions, loadRecordingOptions, resetRecordingOptions, saveRecordingOptions, validateDepthOptions, validateImageOptions, validateRecordingOptions } from "./recording-options.js";
3
4
  import { endSession, recordDepthSample, recordWriteFailure, recordingReducer, startSession } from "./recording-slice.js";
4
5
  import { captureGpsAnchorSample } from "./gps-ar-pose-sampler.js";
5
- import { createPersistenceMiddleware } from "./persistence-middleware.js";
6
+ import { selectAlignmentMatrix, selectFrameTilesInWebXR, selectGpsPositions, selectOdometryPositions, selectOdometryRotations, selectZeroReference } from "./app-selectors.js";
7
+ import { DEFAULT_TRACKING_QUALITY_OPTIONS, computeCompassAgreement, computeConvergence, computeCoverage, computeGpsAccuracy, computeGpsVsFusedDivergence, computeResidualConsensus, computeTrackingQualityReport, createTrackingQualityListenerMiddleware, degradedCountUpdated, firstAgreementReached, matrixDelta, reportUpdated, resetTrackingQuality, selectFirstAgreementObservationIndex, selectRecentAlignments, selectTrackingQuality, snapshotPushed, snapshotsTrimmed, trackingQualityReducer } from "./tracking-quality.js";
8
+ import { createPersistenceMiddleware, slicePrefixOf } from "./persistence-middleware.js";
6
9
  import { createSlamAppStore } from "./create-slam-app-store.js";
7
10
  import { replayRecording } from "./recording-replayer.js";
8
11
  import { DEFAULT_MAX_DELAY_MS, ReplayEngine, computeInterActionDelay, extractActionTimestamp } from "./replay-engine.js";
9
12
  import { subscribeToSelector } from "./subscribe-to-selector.js";
10
- import { selectAlignmentMatrix, selectGpsPositions, selectOdometryPositions, selectOdometryRotations, selectReferencePoints, selectZeroReference } from "./app-selectors.js";
11
13
  import { wireStoreSubscribers } from "./store-subscribers.js";
12
- import { add2dImage, calcRelativeCoordsInMeters, markReferencePoint, recordGpsEvent, setZeroPos } from "gps-plus-slam-js";
13
- export { DEFAULT_MAX_DELAY_MS, DEFAULT_RECORDING_OPTIONS, DEPTH_CONSTRAINTS, IMAGE_CONSTRAINTS, ReplayEngine, STORAGE_KEY, add2dImage, buildRawGpsPoint, buildRecordGpsEventPayload, calcRelativeCoordsInMeters, captureGpsAnchorSample, cloneRecordingOptions, computeInterActionDelay, createGpsPositionHandler, createPersistenceMiddleware, createSlamAppStore, endSession, eulerToQuaternion, extractActionTimestamp, extractOdomPosition, extractOdomRotation, getLastDeviceOrientation, loadRecordingOptions, markReferencePoint, recordDepthSample, recordGpsEvent, recordWriteFailure, recordingReducer, replayRecording, resetCoordinatorState, resetRecordingOptions, saveRecordingOptions, selectAlignmentMatrix, selectGpsPositions, selectOdometryPositions, selectOdometryRotations, selectReferencePoints, selectZeroReference, setZeroPos, startSession, subscribeToSelector, updateDeviceOrientation, validateDepthOptions, validateImageOptions, validateRecordingOptions, wireStoreSubscribers };
14
+ import { add2dImage, calcRelativeCoordsInMeters, recordGpsEvent, setZeroPos } from "gps-plus-slam-js";
15
+ export { DEFAULT_MAX_DELAY_MS, DEFAULT_RECORDING_OPTIONS, DEFAULT_TRACKING_QUALITY_OPTIONS, DEPTH_CONSTRAINTS, IMAGE_CONSTRAINTS, ReplayEngine, STORAGE_KEY, add2dImage, buildRawGpsPoint, buildRecordGpsEventPayload, calcRelativeCoordsInMeters, captureGpsAnchorSample, clearLastRestartedPayload, cloneRecordingOptions, computeCompassAgreement, computeConvergence, computeCoverage, computeGpsAccuracy, computeGpsVsFusedDivergence, computeInterActionDelay, computeResidualConsensus, computeTrackingQualityReport, createGpsPositionHandler, createPersistenceMiddleware, createSlamAppStore, createTrackingQualityListenerMiddleware, degradedCountUpdated, endSession, eulerToQuaternion, extractActionTimestamp, extractOdomPosition, extractOdomRotation, firstAgreementReached, getLastDeviceOrientation, loadRecordingOptions, matrixDelta, originReset, poseLost, poseReceived, recordDepthSample, recordGpsEvent, recordWriteFailure, recordingReducer, replayRecording, reportUpdated, resetCoordinatorState, resetRecordingOptions, resetTracking, resetTrackingQuality, saveRecordingOptions, selectAlignmentMatrix, selectFirstAgreementObservationIndex, selectFrameTilesInWebXR, selectGpsPositions, selectLastRestartedPayload, selectLastSensorOrientation, selectLastValidPose, selectLostFrameCount, selectOdometryPositions, selectOdometryRotations, selectRecentAlignments, selectTrackingPhase, selectTrackingQuality, selectZeroReference, setZeroPos, slicePrefixOf, snapshotPushed, snapshotsTrimmed, startSession, subscribeToSelector, trackingQualityReducer, trackingReducer, updateDeviceOrientation, validateDepthOptions, validateImageOptions, validateRecordingOptions, wireStoreSubscribers };
@@ -1,2 +1,2 @@
1
- import { n as createPersistenceMiddleware, t as PersistenceMiddlewareOptions } from "../persistence-middleware-z-75iisb.js";
2
- export { PersistenceMiddlewareOptions, createPersistenceMiddleware };
1
+ import { n as createPersistenceMiddleware, r as slicePrefixOf, t as PersistenceMiddlewareOptions } from "../persistence-middleware-BkHIqvaA.js";
2
+ export { PersistenceMiddlewareOptions, createPersistenceMiddleware, slicePrefixOf };
@@ -27,31 +27,59 @@ var WriteQueue = class {
27
27
  }
28
28
  };
29
29
  /**
30
+ * Extract the slice prefix from a namespaced Redux action type.
31
+ *
32
+ * `'gpsData/setZeroPos'` → `'gpsData'`. Returns the whole string when there
33
+ * is no slash (e.g. `'@@INIT'`). This is the single point that turns a
34
+ * slice-owned action type into the value the persistence whitelist matches
35
+ * on, so call sites can derive prefixes from real action creators instead of
36
+ * re-typing literals.
37
+ */
38
+ function slicePrefixOf(actionType) {
39
+ const slashIndex = actionType.indexOf("/");
40
+ return slashIndex === -1 ? actionType : actionType.slice(0, slashIndex);
41
+ }
42
+ /** Read `state.recording.isRecording`, defaulting to false for any shape. */
43
+ function readIsRecording(state) {
44
+ return state?.recording?.isRecording ?? false;
45
+ }
46
+ /**
47
+ * Decide whether the just-reduced action belongs to a session whose actions
48
+ * must be persisted. True while recording, and also for the `endSession`
49
+ * action that just flipped `isRecording` to false (Issue 5) so the session's
50
+ * final action is still captured.
51
+ */
52
+ function isInPersistableSession(wasRecording, isRecording, actionType) {
53
+ return isRecording || wasRecording && actionType === "recording/endSession";
54
+ }
55
+ /**
30
56
  * Create a Redux middleware that persists qualifying actions to storage
31
57
  * during active recording sessions.
32
58
  *
33
59
  * Persistence rules:
34
60
  * - Only persists when `state.recording.isRecording` is true (checked AFTER
35
61
  * the action is reduced, so `startSession` itself is included).
36
- * - Persists `gpsData/*` and `recording/*` actions.
62
+ * - Persists actions whose slice prefix is listed in `persistedPrefixes`.
37
63
  * - Excludes `recording/recordWriteFailure` to prevent recursive persistence.
38
- * - Excludes `routing/*`, `refPoints/*`, and any other non-recording actions.
64
+ * - Excludes `routing/*` and any other non-whitelisted actions.
39
65
  * - Uses 1-based indexing for action files (000001.json, 000002.json, …).
40
66
  * - Each middleware instance maintains its own action index (Bug 10 fix).
41
67
  */
42
68
  function createPersistenceMiddleware(options) {
43
- const { storageBackend, onWriteFailure } = options;
69
+ const { storageBackend, onWriteFailure, persistedPrefixes } = options;
70
+ const normalizedPrefixes = persistedPrefixes.map((prefix) => prefix.endsWith("/") ? prefix : `${prefix}/`);
71
+ const excludedActionType = recordWriteFailure.type;
44
72
  let actionIndex = 0;
45
73
  const writeQueue = new WriteQueue();
46
74
  const middleware = (store) => (next) => (action) => {
47
75
  const typedAction = action;
48
76
  const actionType = typeof typedAction.type === "string" ? typedAction.type : null;
49
- const wasRecording = store.getState().recording?.isRecording ?? false;
77
+ const wasRecording = readIsRecording(store.getState());
50
78
  const result = next(action);
51
79
  if (!actionType) return result;
52
80
  if (actionType === "recording/startSession") actionIndex = 0;
53
- if (!((store.getState().recording?.isRecording ?? false) || wasRecording && actionType === "recording/endSession")) return result;
54
- if (!(actionType.startsWith("gpsData/") || actionType.startsWith("recording/") && actionType !== "recording/recordWriteFailure")) return result;
81
+ if (!isInPersistableSession(wasRecording, readIsRecording(store.getState()), actionType)) return result;
82
+ if (!(actionType !== excludedActionType && normalizedPrefixes.some((prefix) => actionType.startsWith(prefix)))) return result;
55
83
  const index = ++actionIndex;
56
84
  writeQueue.enqueue(async () => {
57
85
  try {
@@ -68,4 +96,4 @@ function createPersistenceMiddleware(options) {
68
96
  return middleware;
69
97
  }
70
98
  //#endregion
71
- export { createPersistenceMiddleware };
99
+ export { createPersistenceMiddleware, slicePrefixOf };
@@ -1,2 +1,2 @@
1
- import { _ as validateRecordingOptions, a as IMAGE_CONSTRAINTS, c as RecordingOptionsInput, d as loadRecordingOptions, f as resetRecordingOptions, g as validateImageOptions, h as validateDepthOptions, i as DepthCaptureOptions, l as STORAGE_KEY, m as validateArCrashIsolationOptions, n as DEFAULT_RECORDING_OPTIONS, o as ImageCaptureOptions, p as saveRecordingOptions, r as DEPTH_CONSTRAINTS, s as RecordingOptions, t as ArCrashIsolationOptions, u as cloneRecordingOptions } from "../recording-options-BYUFX8iU.js";
1
+ import { _ as validateRecordingOptions, a as IMAGE_CONSTRAINTS, c as RecordingOptionsInput, d as loadRecordingOptions, f as resetRecordingOptions, g as validateImageOptions, h as validateDepthOptions, i as DepthCaptureOptions, l as STORAGE_KEY, m as validateArCrashIsolationOptions, n as DEFAULT_RECORDING_OPTIONS, o as ImageCaptureOptions, p as saveRecordingOptions, r as DEPTH_CONSTRAINTS, s as RecordingOptions, t as ArCrashIsolationOptions, u as cloneRecordingOptions } from "../recording-options-Dq6IsKAv.js";
2
2
  export { ArCrashIsolationOptions, DEFAULT_RECORDING_OPTIONS, DEPTH_CONSTRAINTS, DepthCaptureOptions, IMAGE_CONSTRAINTS, ImageCaptureOptions, RecordingOptions, RecordingOptionsInput, STORAGE_KEY, cloneRecordingOptions, loadRecordingOptions, resetRecordingOptions, saveRecordingOptions, validateArCrashIsolationOptions, validateDepthOptions, validateImageOptions, validateRecordingOptions };
@@ -1,3 +1,3 @@
1
- import { t as CombinedRootState } from "../combined-root-state-B3SvPNjU.js";
2
- import { n as replayRecording, t as ReplayRecordingOptions } from "../recording-replayer-BFhFs7Mc.js";
1
+ import { L as CombinedRootState } from "../create-slam-app-store-CNsZ3rcX.js";
2
+ import { n as replayRecording, t as ReplayRecordingOptions } from "../recording-replayer-CmCIIZ02.js";
3
3
  export { CombinedRootState, ReplayRecordingOptions, replayRecording };
@@ -1,2 +1,2 @@
1
- import { a as recordWriteFailure, i as recordDepthSample, n as SessionMetadata, o as recordingReducer, r as endSession, s as startSession, t as RecordingState } from "../recording-slice-BiktUIWF.js";
1
+ import { a as recordWriteFailure, i as recordDepthSample, n as SessionMetadata, o as recordingReducer, r as endSession, s as startSession, t as RecordingState } from "../recording-slice-d6OtCrza.js";
2
2
  export { RecordingState, SessionMetadata, endSession, recordDepthSample, recordWriteFailure, recordingReducer, startSession };
@@ -1,2 +1,2 @@
1
- import { a as ReplayAction, c as computeInterActionDelay, i as ProgressCallback, l as extractActionTimestamp, n as DEFAULT_MAX_DELAY_MS, o as ReplayEngine, r as ErrorCallback, s as ReplayState, t as CompleteCallback } from "../replay-engine-B88Va62x.js";
1
+ import { a as ReplayAction, c as computeInterActionDelay, i as ProgressCallback, l as extractActionTimestamp, n as DEFAULT_MAX_DELAY_MS, o as ReplayEngine, r as ErrorCallback, s as ReplayState, t as CompleteCallback } from "../replay-engine-BGBRQyXs.js";
2
2
  export { CompleteCallback, DEFAULT_MAX_DELAY_MS, ErrorCallback, ProgressCallback, ReplayAction, ReplayEngine, ReplayState, computeInterActionDelay, extractActionTimestamp };
@@ -1,3 +1,3 @@
1
- import { t as SubscribableStore } from "../subscribe-to-selector-ghDKYtap.js";
2
- import { n as wireStoreSubscribers, t as StoreSubscriberDeps } from "../store-subscribers-DKKHld49.js";
1
+ import { t as SubscribableStore } from "../subscribe-to-selector-DIHm3BRZ.js";
2
+ import { n as wireStoreSubscribers, t as StoreSubscriberDeps } from "../store-subscribers-Dce_CoJF.js";
3
3
  export { StoreSubscriberDeps, SubscribableStore, wireStoreSubscribers };
@@ -1,6 +1,6 @@
1
- import { fusedGpsFromOdom } from "../utils/fused-path.js";
2
- import { subscribeToSelector } from "./subscribe-to-selector.js";
3
1
  import { selectAlignmentMatrix, selectGpsPositions, selectOdometryPositions, selectOdometryRotations, selectZeroReference } from "./app-selectors.js";
2
+ import { buildMapData } from "../visualization/map-data.js";
3
+ import { subscribeToSelector } from "./subscribe-to-selector.js";
4
4
  import { calcGpsCoords } from "gps-plus-slam-js";
5
5
  import { mat4, vec3 } from "gl-matrix";
6
6
  //#region ../src/state/store-subscribers.ts
@@ -27,6 +27,30 @@ function wireStoreSubscribers(store, deps) {
27
27
  const _odomVec = vec3.create();
28
28
  const _alignedVec = vec3.create();
29
29
  const unsubs = [];
30
+ const alignmentSnapshotGps = [];
31
+ /**
32
+ * Rebuild the full map snapshot from the current store state and hand it to
33
+ * the overlay's `render`. Called whenever the alignment matrix or the GPS
34
+ * positions change — the change-gated subscriptions below provide the
35
+ * throttling, so no extra debouncing is needed. The fused path is always
36
+ * recomputed from the latest matrix inside `buildMapData` (D2).
37
+ */
38
+ function rebuildMap() {
39
+ if (!deps.mapOverlay?.render) return;
40
+ const state = store.getState();
41
+ const rawGpsPath = selectGpsPositions(state).map((p) => ({
42
+ lat: p.latitude,
43
+ lng: p.longitude,
44
+ accuracy: p.latLongAccuracy
45
+ }));
46
+ deps.mapOverlay.render(buildMapData({
47
+ rawGpsPath,
48
+ odometryPositions: selectOdometryPositions(state),
49
+ alignmentMatrix: selectAlignmentMatrix(state),
50
+ zeroRef: selectZeroReference(state),
51
+ alignmentSnapshots: alignmentSnapshotGps
52
+ }));
53
+ }
30
54
  unsubs.push(subscribeToSelector(store, selectAlignmentMatrix, (matrix) => {
31
55
  if (!matrix) return;
32
56
  deps.applyAlignmentMatrix(matrix);
@@ -45,11 +69,15 @@ function wireStoreSubscribers(store, deps) {
45
69
  deps.gpsEventVisualizer.addAlignmentSnapshot(snapshotPos);
46
70
  deps.onAlignmentSnapshot?.(snapshotPos);
47
71
  const zeroRef = selectZeroReference(state);
48
- if (zeroRef && deps.mapOverlay?.addAlignmentSnapshot) {
72
+ if (zeroRef) {
49
73
  const gps = calcGpsCoords(zeroRef, _alignedVec);
50
- deps.mapOverlay.addAlignmentSnapshot(gps.lat, gps.lon);
74
+ alignmentSnapshotGps.push({
75
+ lat: gps.lat,
76
+ lng: gps.lon
77
+ });
51
78
  }
52
79
  }
80
+ rebuildMap();
53
81
  }));
54
82
  unsubs.push(subscribeToSelector(store, selectGpsPositions, (gpsPositions, prevPositions) => {
55
83
  const prevCount = prevPositions?.length ?? 0;
@@ -62,16 +90,13 @@ function wireStoreSubscribers(store, deps) {
62
90
  const gpsPoint = gpsPositions[i];
63
91
  const odomPos = odomPositions[i];
64
92
  if (gpsPoint && odomPos) {
65
- deps.gpsEventVisualizer.addGpsEvent(gpsPoint.coordinates, odomPos);
93
+ const accuracy = deps.showAccuracySpheres ? {
94
+ horizontal: gpsPoint.latLongAccuracy,
95
+ vertical: gpsPoint.altitudeAccuracy
96
+ } : void 0;
97
+ deps.gpsEventVisualizer.addGpsEvent(gpsPoint.coordinates, odomPos, accuracy);
66
98
  deps.onNewGpsPosition?.(gpsPoint.coordinates);
67
99
  deps.onNewGpsLatLng?.(gpsPoint.latitude, gpsPoint.longitude);
68
- deps.mapOverlay?.addRawGpsPoint?.(gpsPoint.latitude, gpsPoint.longitude);
69
- const alignmentMatrix = selectAlignmentMatrix(state);
70
- const zero = selectZeroReference(state);
71
- if (alignmentMatrix && zero && deps.mapOverlay?.addFusedPoint) {
72
- const fusedGps = fusedGpsFromOdom(alignmentMatrix, odomPos, zero);
73
- deps.mapOverlay.addFusedPoint(fusedGps.lat, fusedGps.lon);
74
- }
75
100
  const odomRot = odomRotations[i];
76
101
  if (odomRot) deps.onNewOdomPose?.(odomPos, odomRot);
77
102
  }
@@ -80,6 +105,7 @@ function wireStoreSubscribers(store, deps) {
80
105
  const lastGpsPoint = gpsPositions[gpsPositions.length - 1];
81
106
  deps.mapOverlay.setGpsPosition(lastGpsPoint.latitude, lastGpsPoint.longitude);
82
107
  }
108
+ rebuildMap();
83
109
  }));
84
110
  return () => {
85
111
  for (const unsub of unsubs) unsub();
@@ -1,2 +1,2 @@
1
- import { n as subscribeToSelector, t as SubscribableStore } from "../subscribe-to-selector-ghDKYtap.js";
1
+ import { n as subscribeToSelector, t as SubscribableStore } from "../subscribe-to-selector-DIHm3BRZ.js";
2
2
  export { SubscribableStore, subscribeToSelector };
@@ -0,0 +1,2 @@
1
+ import { A as resetTrackingQuality, C as computeResidualConsensus, D as firstAgreementReached, E as degradedCountUpdated, F as snapshotsTrimmed, I as trackingQualityReducer, M as selectRecentAlignments, N as selectTrackingQuality, O as matrixDelta, P as snapshotPushed, S as computeGpsVsFusedDivergence, T as createTrackingQualityListenerMiddleware, _ as TrackingQualityState, b as computeCoverage, c as CompassAgreementResult, d as DEFAULT_TRACKING_QUALITY_OPTIONS, f as GpsAccuracyResult, g as TrackingQualitySliceState, h as TrackingQualityReport, j as selectFirstAgreementObservationIndex, k as reportUpdated, l as ConvergenceResult, m as TrackingQualityOptions, p as ResidualConsensusResult, s as AlignmentSnapshot, u as CoverageResult, v as computeCompassAgreement, w as computeTrackingQualityReport, x as computeGpsAccuracy, y as computeConvergence } from "../create-slam-app-store-CNsZ3rcX.js";
2
+ export { AlignmentSnapshot, CompassAgreementResult, ConvergenceResult, CoverageResult, DEFAULT_TRACKING_QUALITY_OPTIONS, GpsAccuracyResult, ResidualConsensusResult, TrackingQualityOptions, TrackingQualityReport, TrackingQualitySliceState, TrackingQualityState, computeCompassAgreement, computeConvergence, computeCoverage, computeGpsAccuracy, computeGpsVsFusedDivergence, computeResidualConsensus, computeTrackingQualityReport, createTrackingQualityListenerMiddleware, degradedCountUpdated, firstAgreementReached, matrixDelta, reportUpdated, resetTrackingQuality, selectFirstAgreementObservationIndex, selectRecentAlignments, selectTrackingQuality, snapshotPushed, snapshotsTrimmed, trackingQualityReducer };