@mentra/engine 3.1.0-dev.44 → 3.1.0-dev.47

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.
@@ -28,6 +28,7 @@ export type MentraLiveOtaFlowPage = "check" | "progress"
28
28
  export type MentraLiveOtaScreen =
29
29
  | "initializing"
30
30
  | "checking"
31
+ | "finishing"
31
32
  | "update_available"
32
33
  | "wifi_required"
33
34
  | "up_to_date"
@@ -94,6 +95,8 @@ export type MentraLiveOtaState = {
94
95
  canDiscard: boolean
95
96
  canOpenWifiSetup: boolean
96
97
  continueDisabled: boolean
98
+ /** True only after an approved update session reaches a final no-update check. */
99
+ completedUpdate: boolean
97
100
  /** Release labels for the offered or just-completed coordinated update. */
98
101
  releaseTransition: MentraLiveOtaReleaseTransition | null
99
102
  /** Release notes crossed by this update, newest first. Populated on completion. */
@@ -163,10 +166,10 @@ function installProgress(snapshot: OtaInstallSnapshot): number | null {
163
166
  const isDownload = otaStatus?.phase === "download"
164
167
  const totalSteps = otaStatus?.totalSteps ?? 1
165
168
  const rawPercent = isDownload
166
- ? otaStatus?.stepPercent ?? 0
169
+ ? (otaStatus?.stepPercent ?? 0)
167
170
  : totalSteps >= 2
168
- ? otaStatus?.overallPercent ?? 0
169
- : otaStatus?.stepPercent ?? 0
171
+ ? (otaStatus?.overallPercent ?? 0)
172
+ : (otaStatus?.stepPercent ?? 0)
170
173
  return Math.min(Math.max(rawPercent, snapshot.mtkInstallStallSimulatedPercent ?? 0, 0), 100)
171
174
  }
172
175
 
@@ -215,6 +218,7 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
215
218
  const [completedReleaseTransition, setCompletedReleaseTransition] = useState<MentraLiveOtaReleaseTransition | null>(
216
219
  null,
217
220
  )
221
+ const [completedUpdate, setCompletedUpdate] = useState(false)
218
222
  const [completedChangelogs, setCompletedChangelogs] = useState<ReleaseChangelog[]>([])
219
223
  const [checkGeneration, setCheckGeneration] = useState(0)
220
224
  const performCheckGenerationRef = useRef(0)
@@ -249,6 +253,7 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
249
253
  const returnToCheck = useCallback(() => {
250
254
  installActionPendingRef.current = false
251
255
  autoChainAdvancedRef.current = false
256
+ setCheckState("checking")
252
257
  setPage("check")
253
258
  setCheckGeneration((generation) => generation + 1)
254
259
  }, [])
@@ -259,6 +264,28 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
259
264
  setPage("progress")
260
265
  }, [])
261
266
 
267
+ const continueApprovedChain = useCallback(
268
+ (result: OtaCheckCurrentGlassesResult): boolean => {
269
+ if (installActionPendingRef.current || !isOtaAutoChainActive() || !result.updateInfo) return false
270
+ const snapshot = ota.snapshot()
271
+ if (!snapshot.wifiStatusKnown || (!snapshot.wifiConnected && snapshot.hotspotOtaVersion !== 1)) return false
272
+
273
+ const admission = tryAdvanceOtaAutoChain(
274
+ otaAutoChainFingerprint(result),
275
+ result.updateInfo.isDowngrade === true,
276
+ releaseRangeTargetVersion(result),
277
+ result.releaseVersion,
278
+ )
279
+ if (!admission.advance) return false
280
+
281
+ checkCompletedRef.current = true
282
+ ota.installSession.prepare(result)
283
+ navigateToProgress()
284
+ return true
285
+ },
286
+ [navigateToProgress],
287
+ )
288
+
262
289
  useEffect(() => {
263
290
  if (!runtimeReady || page !== "check") return
264
291
  const MIN_DISPLAY_TIME_MS = 1100
@@ -364,34 +391,21 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
364
391
  const fromVersion = currentReleaseVersion(ota.snapshot().appVersion)
365
392
  setOfferedReleaseTransition(result.releaseVersion ? {fromVersion, toVersion: result.releaseVersion} : null)
366
393
  }
367
- if (isOtaAutoChainActive()) {
368
- const snapshot = ota.snapshot()
369
- if (!snapshot.wifiStatusKnown) return
370
- if (!snapshot.wifiConnected && snapshot.hotspotOtaVersion !== 1) {
371
- stopOtaAutoChain()
372
- } else {
373
- const admission = tryAdvanceOtaAutoChain(
374
- fingerprint,
375
- result.updateInfo.isDowngrade === true,
376
- releaseRangeTargetVersion(result),
377
- result.releaseVersion,
378
- )
379
- if (admission.advance) {
380
- checkCompletedRef.current = true
381
- ota.installSession.prepare(result)
382
- navigateToProgress()
383
- return
384
- }
385
- }
394
+ if (isOtaAutoChainActive() && !ota.snapshot().wifiStatusKnown) {
395
+ checkCompletedRef.current = true
396
+ return
386
397
  }
398
+ if (continueApprovedChain(result)) return
387
399
  checkCompletedRef.current = true
388
400
  setCheckState("update_available")
389
401
  return
390
402
  }
391
- if (isOtaAutoChainActive()) {
403
+ const completedApprovedSession = isOtaAutoChainActive()
404
+ if (completedApprovedSession) {
392
405
  setCompletedChangelogs(releaseChangelogsForActiveChain())
393
406
  setCompletedReleaseTransition(releaseTransitionFromRange(otaAutoChainReleaseRange()))
394
407
  }
408
+ setCompletedUpdate(completedApprovedSession)
395
409
  stopOtaAutoChain()
396
410
  checkCompletedRef.current = true
397
411
  ota.clearUpdateAvailable()
@@ -412,7 +426,34 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
412
426
  cancelled = true
413
427
  if (reconnectTimeout) clearTimeout(reconnectTimeout)
414
428
  }
415
- }, [checkGeneration, navigateToProgress, otaSnapshot.connected, otaSnapshot.wifiStatusKnown, page, runtimeReady])
429
+ }, [checkGeneration, continueApprovedChain, otaSnapshot.connected, otaSnapshot.wifiStatusKnown, page, runtimeReady])
430
+
431
+ useEffect(() => {
432
+ if (
433
+ !runtimeReady ||
434
+ page !== "check" ||
435
+ (checkState !== "checking" && checkState !== "update_available") ||
436
+ !otaSnapshot.wifiStatusKnown ||
437
+ !isOtaAutoChainActive()
438
+ ) {
439
+ return
440
+ }
441
+ const result = selectedCheckResultRef.current
442
+ if (!result?.updateAvailable || !result.updateInfo) return
443
+ if (!otaSnapshot.wifiConnected && otaSnapshot.hotspotOtaVersion !== 1) {
444
+ setCheckState("update_available")
445
+ return
446
+ }
447
+ continueApprovedChain(result)
448
+ }, [
449
+ checkState,
450
+ continueApprovedChain,
451
+ otaSnapshot.hotspotOtaVersion,
452
+ otaSnapshot.wifiConnected,
453
+ otaSnapshot.wifiStatusKnown,
454
+ page,
455
+ runtimeReady,
456
+ ])
416
457
 
417
458
  useEffect(() => {
418
459
  if (!runtimeReady || page !== "progress") return
@@ -459,6 +500,7 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
459
500
  const check = useCallback(() => {
460
501
  setOfferedReleaseTransition(null)
461
502
  setCompletedReleaseTransition(null)
503
+ setCompletedUpdate(false)
462
504
  setCompletedChangelogs([])
463
505
  setPage("check")
464
506
  setCheckState("checking")
@@ -483,6 +525,7 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
483
525
  return
484
526
  }
485
527
  ota.installSession.prepare(result)
528
+ setCompletedUpdate(false)
486
529
  setCompletedChangelogs([])
487
530
  if (updateFingerprint) {
488
531
  const fromVersion = offeredReleaseTransition
@@ -534,6 +577,7 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
534
577
  const state = useMemo<MentraLiveOtaState>(() => {
535
578
  const hotspotSupported = otaSnapshot.hotspotOtaVersion === 1
536
579
  const canInstall = otaSnapshot.wifiStatusKnown && (otaSnapshot.wifiConnected || hotspotSupported)
580
+ const autoChainActive = isOtaAutoChainActive()
537
581
  if (!runtimeReady) {
538
582
  return {
539
583
  screen: "initializing",
@@ -563,6 +607,7 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
563
607
  canDiscard: false,
564
608
  canOpenWifiSetup: false,
565
609
  continueDisabled: false,
610
+ completedUpdate: false,
566
611
  releaseTransition: null,
567
612
  changelogs: [],
568
613
  }
@@ -570,26 +615,22 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
570
615
 
571
616
  if (page === "check") {
572
617
  const wifiRequired = otaSnapshot.wifiStatusKnown && !otaSnapshot.wifiConnected && !hotspotSupported
573
- const screen: MentraLiveOtaScreen =
574
- checkState === "checking"
575
- ? "checking"
576
- : checkState === "update_available"
577
- ? wifiRequired
578
- ? "wifi_required"
579
- : "update_available"
580
- : checkState === "no_update"
581
- ? "up_to_date"
582
- : checkState === "dev_build"
583
- ? "dev_build"
584
- : errorKind === "pin_unavailable"
585
- ? "update_info_unavailable"
586
- : "check_failed"
587
- const error: MentraLiveOtaError | null =
588
- screen === "check_failed"
589
- ? {code: "check_failed", message: "Couldn't check for updates. Please check your connection and try again."}
590
- : screen === "update_info_unavailable"
591
- ? {code: "update_info_unavailable", message: "Update information for this app version is unavailable."}
592
- : null
618
+ let screen: MentraLiveOtaScreen
619
+ if (checkState === "checking") screen = autoChainActive ? "finishing" : "checking"
620
+ else if (checkState === "update_available") screen = wifiRequired ? "wifi_required" : "update_available"
621
+ else if (checkState === "no_update") screen = "up_to_date"
622
+ else if (checkState === "dev_build") screen = "dev_build"
623
+ else screen = errorKind === "pin_unavailable" ? "update_info_unavailable" : "check_failed"
624
+
625
+ let error: MentraLiveOtaError | null = null
626
+ if (screen === "check_failed") {
627
+ error = {
628
+ code: "check_failed",
629
+ message: "Couldn't check for updates. Please check your connection and try again.",
630
+ }
631
+ } else if (screen === "update_info_unavailable") {
632
+ error = {code: "update_info_unavailable", message: "Update information for this app version is unavailable."}
633
+ }
593
634
  return {
594
635
  screen,
595
636
  connected: otaSnapshot.connected,
@@ -614,13 +655,17 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
614
655
  canInstall: screen === "update_available" && canInstall,
615
656
  canRetry: screen === "check_failed",
616
657
  canFinish: screen === "up_to_date" || screen === "dev_build" || screen === "update_info_unavailable",
617
- canDismiss: (screen === "update_available" || screen === "wifi_required") && !isUpdateRequired,
658
+ canDismiss:
659
+ (screen === "update_available" || screen === "wifi_required") && !isUpdateRequired && !autoChainActive,
618
660
  canDiscard: false,
619
661
  canOpenWifiSetup: screen === "wifi_required",
620
662
  continueDisabled: false,
663
+ completedUpdate: screen === "up_to_date" && completedUpdate,
621
664
  releaseTransition:
622
665
  screen === "update_available" || screen === "wifi_required"
623
- ? offeredReleaseTransition
666
+ ? autoChainActive
667
+ ? releaseTransitionFromRange(otaAutoChainReleaseRange())
668
+ : offeredReleaseTransition
624
669
  : screen === "up_to_date"
625
670
  ? completedReleaseTransition
626
671
  : null,
@@ -641,7 +686,8 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
641
686
  const displayedError = requiresGlassesReboot
642
687
  ? BES_INSTALL_RESTART_MESSAGE
643
688
  : installSnapshot.errorMsg || getOtaErrorMessage(installSnapshot.otaStatus?.error)
644
- const screen = progressScreen(installSnapshot)
689
+ const progressState = progressScreen(installSnapshot)
690
+ const screen = progressState === "complete" && autoChainActive ? "finishing" : progressState
645
691
  const error =
646
692
  screen === "failed"
647
693
  ? {
@@ -682,6 +728,7 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
682
728
  canDiscard: screen === "disconnected",
683
729
  canOpenWifiSetup: screen === "failed" && showChangeWifi,
684
730
  continueDisabled: installSnapshot.continueButtonDisabled,
731
+ completedUpdate: false,
685
732
  releaseTransition: releaseTransitionFromRange(otaAutoChainReleaseRange()),
686
733
  changelogs,
687
734
  }
@@ -689,6 +736,7 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
689
736
  checkState,
690
737
  completedChangelogs,
691
738
  completedReleaseTransition,
739
+ completedUpdate,
692
740
  errorKind,
693
741
  firmwareRestarting,
694
742
  installSnapshot,